@termix-ssh/plugin-sdk 1.0.0

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 (236) hide show
  1. package/README.md +52 -0
  2. package/cli/commands/build.mjs +246 -0
  3. package/cli/commands/migrations.mjs +248 -0
  4. package/cli/commands/pack.mjs +42 -0
  5. package/cli/commands/sign.mjs +83 -0
  6. package/cli/commands/test.mjs +33 -0
  7. package/cli/commands/validate.mjs +215 -0
  8. package/cli/index.mjs +65 -0
  9. package/cli/lib/changelog.mjs +126 -0
  10. package/cli/lib/externals.mjs +46 -0
  11. package/cli/lib/plugin-dir.mjs +29 -0
  12. package/cli/lib/signing.mjs +86 -0
  13. package/cli/lib/static-url-imports.mjs +54 -0
  14. package/cli/lib/tmxplug.mjs +106 -0
  15. package/cli/patches/guacamole-common-js-flush.cjs +76 -0
  16. package/cli/patches/xterm-android-ime.cjs +130 -0
  17. package/client.d.ts +13 -0
  18. package/dist/backend.d.ts +1777 -0
  19. package/dist/backend.js +84 -0
  20. package/dist/capabilities.d.ts +38 -0
  21. package/dist/capabilities.js +71 -0
  22. package/dist/db.d.ts +112 -0
  23. package/dist/db.js +189 -0
  24. package/dist/ddl.d.ts +76 -0
  25. package/dist/ddl.js +678 -0
  26. package/dist/desktop.d.ts +346 -0
  27. package/dist/desktop.js +5 -0
  28. package/dist/frontend.d.ts +1206 -0
  29. package/dist/frontend.js +388 -0
  30. package/dist/host/chunk-F3SDZDDG.js +6017 -0
  31. package/dist/host/chunk-XGWE7BTJ.js +90 -0
  32. package/dist/host/chunk-XH5NXL6Y.js +56314 -0
  33. package/dist/host/chunk-YC2MAKSP.js +14 -0
  34. package/dist/host/linked-server-FZGWQW32.js +12 -0
  35. package/dist/host/rbac-api-6KDMBVDZ.js +52 -0
  36. package/dist/host/testing-host.js +414 -0
  37. package/dist/host/theme.css +91 -0
  38. package/dist/host/types/src/types/auth-protocols.d.ts +10 -0
  39. package/dist/host/types/src/types/connection-log.d.ts +13 -0
  40. package/dist/host/types/src/types/credential-sidebar-preferences.d.ts +38 -0
  41. package/dist/host/types/src/types/host-defaults.d.ts +60 -0
  42. package/dist/host/types/src/types/host-sidebar-preferences.d.ts +55 -0
  43. package/dist/host/types/src/types/index.d.ts +298 -0
  44. package/dist/host/types/src/types/keybindings.d.ts +27 -0
  45. package/dist/host/types/src/types/ui-preferences.d.ts +102 -0
  46. package/dist/host/types/src/types/ui-types.d.ts +260 -0
  47. package/dist/host/types/src/ui/api/admin-user-data-api.d.ts +11 -0
  48. package/dist/host/types/src/ui/api/auth-methods-api.d.ts +63 -0
  49. package/dist/host/types/src/ui/api/credential-sidebar-preferences-api.d.ts +3 -0
  50. package/dist/host/types/src/ui/api/credentials-api.d.ts +56 -0
  51. package/dist/host/types/src/ui/api/dashboard-api.d.ts +23 -0
  52. package/dist/host/types/src/ui/api/external-account-api.d.ts +8 -0
  53. package/dist/host/types/src/ui/api/host-sidebar-preferences-api.d.ts +3 -0
  54. package/dist/host/types/src/ui/api/host-status-api.d.ts +11 -0
  55. package/dist/host/types/src/ui/api/open-tabs-api.d.ts +74 -0
  56. package/dist/host/types/src/ui/api/plugins-api.d.ts +128 -0
  57. package/dist/host/types/src/ui/api/rbac-api.d.ts +167 -0
  58. package/dist/host/types/src/ui/api/settings-api.d.ts +22 -0
  59. package/dist/host/types/src/ui/api/ssh-host-management-api.d.ts +65 -0
  60. package/dist/host/types/src/ui/api/sync-api.d.ts +93 -0
  61. package/dist/host/types/src/ui/api/system-status-api.d.ts +49 -0
  62. package/dist/host/types/src/ui/api/ui-preferences-api.d.ts +8 -0
  63. package/dist/host/types/src/ui/api/user-management-api.d.ts +80 -0
  64. package/dist/host/types/src/ui/auth/Auth.d.ts +12 -0
  65. package/dist/host/types/src/ui/auth/auth-bits.d.ts +11 -0
  66. package/dist/host/types/src/ui/auth/silent-signin.d.ts +2 -0
  67. package/dist/host/types/src/ui/components/FullScreenAppWrapper.d.ts +9 -0
  68. package/dist/host/types/src/ui/components/alert-dialog.d.ts +14 -0
  69. package/dist/host/types/src/ui/components/alert.d.ts +9 -0
  70. package/dist/host/types/src/ui/components/badge.d.ts +9 -0
  71. package/dist/host/types/src/ui/components/button.d.ts +13 -0
  72. package/dist/host/types/src/ui/components/card-grid/CardGridCanvas.d.ts +22 -0
  73. package/dist/host/types/src/ui/components/card-grid/layout-utils.d.ts +26 -0
  74. package/dist/host/types/src/ui/components/card-grid/types.d.ts +29 -0
  75. package/dist/host/types/src/ui/components/card-masonry.d.ts +16 -0
  76. package/dist/host/types/src/ui/components/card.d.ts +11 -0
  77. package/dist/host/types/src/ui/components/charts/BarSeries.d.ts +16 -0
  78. package/dist/host/types/src/ui/components/charts/LineChart.d.ts +17 -0
  79. package/dist/host/types/src/ui/components/charts/RadialGauge.d.ts +18 -0
  80. package/dist/host/types/src/ui/components/charts/Sparkline.d.ts +22 -0
  81. package/dist/host/types/src/ui/components/charts/StatRow.d.ts +15 -0
  82. package/dist/host/types/src/ui/components/charts/geometry.d.ts +20 -0
  83. package/dist/host/types/src/ui/components/charts/index.d.ts +4 -0
  84. package/dist/host/types/src/ui/components/checkbox.d.ts +4 -0
  85. package/dist/host/types/src/ui/components/connection/ConnectionGate.d.ts +56 -0
  86. package/dist/host/types/src/ui/components/connection/ConnectionLogPanel.d.ts +9 -0
  87. package/dist/host/types/src/ui/components/connection/ConnectionScreen.d.ts +34 -0
  88. package/dist/host/types/src/ui/components/connection/connection-status.d.ts +1 -0
  89. package/dist/host/types/src/ui/components/data-view.d.ts +32 -0
  90. package/dist/host/types/src/ui/components/dialog.d.ts +17 -0
  91. package/dist/host/types/src/ui/components/dropdown-menu.d.ts +29 -0
  92. package/dist/host/types/src/ui/components/empty-state.d.ts +19 -0
  93. package/dist/host/types/src/ui/components/form-fields.d.ts +115 -0
  94. package/dist/host/types/src/ui/components/input.d.ts +3 -0
  95. package/dist/host/types/src/ui/components/kbd.d.ts +12 -0
  96. package/dist/host/types/src/ui/components/label.d.ts +4 -0
  97. package/dist/host/types/src/ui/components/manager-card.d.ts +25 -0
  98. package/dist/host/types/src/ui/components/meter.d.ts +14 -0
  99. package/dist/host/types/src/ui/components/metric-card.d.ts +18 -0
  100. package/dist/host/types/src/ui/components/panel-layout.d.ts +83 -0
  101. package/dist/host/types/src/ui/components/password-input.d.ts +4 -0
  102. package/dist/host/types/src/ui/components/popover.d.ts +7 -0
  103. package/dist/host/types/src/ui/components/scroll-area.d.ts +5 -0
  104. package/dist/host/types/src/ui/components/section-card.d.ts +29 -0
  105. package/dist/host/types/src/ui/components/select.d.ts +15 -0
  106. package/dist/host/types/src/ui/components/select2.d.ts +8 -0
  107. package/dist/host/types/src/ui/components/separator.d.ts +4 -0
  108. package/dist/host/types/src/ui/components/sheet.d.ts +14 -0
  109. package/dist/host/types/src/ui/components/sidebar.d.ts +69 -0
  110. package/dist/host/types/src/ui/components/skeleton.d.ts +2 -0
  111. package/dist/host/types/src/ui/components/slider.d.ts +4 -0
  112. package/dist/host/types/src/ui/components/sonner.d.ts +4 -0
  113. package/dist/host/types/src/ui/components/surface/prompt-styles.d.ts +4 -0
  114. package/dist/host/types/src/ui/components/surface/surface-scope.d.ts +79 -0
  115. package/dist/host/types/src/ui/components/switch.d.ts +4 -0
  116. package/dist/host/types/src/ui/components/tab-strip.d.ts +19 -0
  117. package/dist/host/types/src/ui/components/tabs.d.ts +7 -0
  118. package/dist/host/types/src/ui/components/textarea.d.ts +4 -0
  119. package/dist/host/types/src/ui/components/theme-provider.d.ts +14 -0
  120. package/dist/host/types/src/ui/components/tooltip.d.ts +7 -0
  121. package/dist/host/types/src/ui/contexts/BrandingContext.d.ts +15 -0
  122. package/dist/host/types/src/ui/contexts/UiPreferencesContext.d.ts +38 -0
  123. package/dist/host/types/src/ui/contexts/branding-document.d.ts +10 -0
  124. package/dist/host/types/src/ui/dashboard/dashboard-cards-registry.d.ts +30 -0
  125. package/dist/host/types/src/ui/hooks/use-action-slot.d.ts +10 -0
  126. package/dist/host/types/src/ui/hooks/use-adaptive-polling.d.ts +5 -0
  127. package/dist/host/types/src/ui/hooks/use-mobile.d.ts +1 -0
  128. package/dist/host/types/src/ui/hooks/use-permissions.d.ts +29 -0
  129. package/dist/host/types/src/ui/hooks/use-status-color-scheme.d.ts +12 -0
  130. package/dist/host/types/src/ui/hooks/use-sync-status.d.ts +4 -0
  131. package/dist/host/types/src/ui/hooks/useSshAuthProviders.d.ts +17 -0
  132. package/dist/host/types/src/ui/i18n/i18n.d.ts +52 -0
  133. package/dist/host/types/src/ui/lib/ServerStatusContext.d.ts +33 -0
  134. package/dist/host/types/src/ui/lib/adaptive-polling.d.ts +29 -0
  135. package/dist/host/types/src/ui/lib/adaptive-resource-budget.d.ts +39 -0
  136. package/dist/host/types/src/ui/lib/app-keyboard-shortcuts.d.ts +8 -0
  137. package/dist/host/types/src/ui/lib/base-path.d.ts +1 -0
  138. package/dist/host/types/src/ui/lib/clipboard-provider.d.ts +9 -0
  139. package/dist/host/types/src/ui/lib/clipboard.d.ts +20 -0
  140. package/dist/host/types/src/ui/lib/connection-origin.d.ts +47 -0
  141. package/dist/host/types/src/ui/lib/db-health-monitor.d.ts +34 -0
  142. package/dist/host/types/src/ui/lib/device-id.d.ts +1 -0
  143. package/dist/host/types/src/ui/lib/electron.d.ts +1 -0
  144. package/dist/host/types/src/ui/lib/embedded-server-status.d.ts +15 -0
  145. package/dist/host/types/src/ui/lib/error-message.d.ts +9 -0
  146. package/dist/host/types/src/ui/lib/frontend-logger.d.ts +67 -0
  147. package/dist/host/types/src/ui/lib/global-shortcut-handler.d.ts +3 -0
  148. package/dist/host/types/src/ui/lib/host-defaults-context.d.ts +48 -0
  149. package/dist/host/types/src/ui/lib/hosts-request-cache.d.ts +9 -0
  150. package/dist/host/types/src/ui/lib/keybinding-match.d.ts +3 -0
  151. package/dist/host/types/src/ui/lib/linked-server.d.ts +10 -0
  152. package/dist/host/types/src/ui/lib/local-adaptive-engine.d.ts +40 -0
  153. package/dist/host/types/src/ui/lib/permissions.d.ts +16 -0
  154. package/dist/host/types/src/ui/lib/plugin-i18n.d.ts +11 -0
  155. package/dist/host/types/src/ui/lib/plugin-icon.d.ts +11 -0
  156. package/dist/host/types/src/ui/lib/plugin-transport.d.ts +50 -0
  157. package/dist/host/types/src/ui/lib/registry.d.ts +29 -0
  158. package/dist/host/types/src/ui/lib/rem.d.ts +7 -0
  159. package/dist/host/types/src/ui/lib/remote-server-api.d.ts +11 -0
  160. package/dist/host/types/src/ui/lib/server-status-store.d.ts +37 -0
  161. package/dist/host/types/src/ui/lib/sync-events.d.ts +2 -0
  162. package/dist/host/types/src/ui/lib/sync-status.d.ts +6 -0
  163. package/dist/host/types/src/ui/lib/tab-jump-hotkey.d.ts +4 -0
  164. package/dist/host/types/src/ui/lib/theme.d.ts +21 -0
  165. package/dist/host/types/src/ui/lib/ttl-request-cache.d.ts +10 -0
  166. package/dist/host/types/src/ui/lib/usage-color.d.ts +5 -0
  167. package/dist/host/types/src/ui/lib/utils.d.ts +2 -0
  168. package/dist/host/types/src/ui/lib/visible-interval.d.ts +5 -0
  169. package/dist/host/types/src/ui/lib/widget-title.d.ts +8 -0
  170. package/dist/host/types/src/ui/lib/ws-auth.d.ts +1 -0
  171. package/dist/host/types/src/ui/main-axios.d.ts +170 -0
  172. package/dist/host/types/src/ui/plugin-host/PluginViewPlaceholder.d.ts +13 -0
  173. package/dist/host/types/src/ui/plugin-host/app.d.ts +18 -0
  174. package/dist/host/types/src/ui/plugin-host/auth-registry.d.ts +50 -0
  175. package/dist/host/types/src/ui/plugin-host/bridge.d.ts +26 -0
  176. package/dist/host/types/src/ui/plugin-host/component-registry.d.ts +24 -0
  177. package/dist/host/types/src/ui/plugin-host/desktop.d.ts +7 -0
  178. package/dist/host/types/src/ui/plugin-host/extension-registry.d.ts +16 -0
  179. package/dist/host/types/src/ui/plugin-host/host-scope.d.ts +26 -0
  180. package/dist/host/types/src/ui/plugin-host/loader.d.ts +52 -0
  181. package/dist/host/types/src/ui/plugin-host/plugin-store.d.ts +40 -0
  182. package/dist/host/types/src/ui/plugin-host/scope.d.ts +20 -0
  183. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +99 -0
  184. package/dist/host/types/src/ui/plugin-host/shell-bridge.d.ts +67 -0
  185. package/dist/host/types/src/ui/plugin-host/view-ownership.d.ts +31 -0
  186. package/dist/host/types/src/ui/settings/HostPluginSections.d.ts +31 -0
  187. package/dist/host/types/src/ui/settings/SettingsFields.d.ts +22 -0
  188. package/dist/host/types/src/ui/settings/host-feature-tabs.d.ts +11 -0
  189. package/dist/host/types/src/ui/settings/settings-components.d.ts +32 -0
  190. package/dist/host/types/src/ui/settings/settings-fields-util.d.ts +11 -0
  191. package/dist/host/types/src/ui/shell/ActionSlot.d.ts +41 -0
  192. package/dist/host/types/src/ui/shell/TabContext.d.ts +30 -0
  193. package/dist/host/types/src/ui/shell/action-registry.d.ts +99 -0
  194. package/dist/host/types/src/ui/shell/keybinding-registry.d.ts +62 -0
  195. package/dist/host/types/src/ui/shell/palette-registry.d.ts +55 -0
  196. package/dist/host/types/src/ui/shell/panel-registry.d.ts +24 -0
  197. package/dist/host/types/src/ui/shell/tab-registry.d.ts +92 -0
  198. package/dist/host/types/src/ui/sidebar/HostManagerTabs.d.ts +65 -0
  199. package/dist/host/types/src/ui/sidebar/host-contributions.d.ts +72 -0
  200. package/dist/host/types/src/ui/sidebar/host-defaults/catalog.d.ts +17 -0
  201. package/dist/host/types/src/ui/sidebar/host-protocols.d.ts +49 -0
  202. package/dist/host/types/src/ui/sidebar/quick-connect-host.d.ts +21 -0
  203. package/dist/host/types/src/ui/sidebar/rail-items.d.ts +103 -0
  204. package/dist/host/types/src/ui/ssh/connection-log/ConnectionLogContext.d.ts +17 -0
  205. package/dist/host/types/src/ui/ssh/dialogs/BrowserSignInDialog.d.ts +18 -0
  206. package/dist/host/types/src/ui/ssh/dialogs/HostKeyVerificationDialog.d.ts +17 -0
  207. package/dist/host/types/src/ui/ssh/dialogs/PassphraseDialog.d.ts +15 -0
  208. package/dist/host/types/src/ui/ssh/dialogs/SSHAuthDialog.d.ts +20 -0
  209. package/dist/host/types/src/ui/ssh/dialogs/TOTPDialog.d.ts +13 -0
  210. package/dist/host/ui.d.ts +1 -0
  211. package/dist/host/ui.js +31754 -0
  212. package/dist/host/use-permissions-NULZL43J.js +18 -0
  213. package/dist/host-commands.d.ts +89 -0
  214. package/dist/host-commands.js +387 -0
  215. package/dist/manifest.d.ts +461 -0
  216. package/dist/manifest.js +1499 -0
  217. package/dist/settings.d.ts +43 -0
  218. package/dist/settings.js +168 -0
  219. package/dist/ssh-certs.d.ts +25 -0
  220. package/dist/ssh-certs.js +234 -0
  221. package/dist/ssh-options.d.ts +23 -0
  222. package/dist/ssh-options.js +1 -0
  223. package/dist/table-builder.d.ts +26 -0
  224. package/dist/table-builder.js +87 -0
  225. package/dist/testing/safe-ports.d.ts +10 -0
  226. package/dist/testing/safe-ports.js +59 -0
  227. package/dist/testing/setup.d.ts +7 -0
  228. package/dist/testing/setup.js +146 -0
  229. package/dist/testing.d.ts +537 -0
  230. package/dist/testing.js +1451 -0
  231. package/dist/vitest-preset.d.ts +54 -0
  232. package/dist/vitest-preset.js +96 -0
  233. package/package.json +143 -0
  234. package/schema/changelog.schema.json +67 -0
  235. package/schema/manifest.schema.json +1160 -0
  236. package/tsconfig.plugin.json +31 -0
@@ -0,0 +1,67 @@
1
+ import type { Host } from "../../types/ui-types";
2
+ import type { TabShellCallbacks } from "../shell/tab-registry";
3
+ /**
4
+ * The live shell, as plugins see it.
5
+ *
6
+ * AppShell owns tabs and hosts in React state. It publishes callbacks and
7
+ * the host list here on every render, and plugin code (the app object, the
8
+ * SDK hooks, registered host actions) calls through this module, so nothing
9
+ * has to be threaded through props into a plugin.
10
+ */
11
+ type Layout = {
12
+ version: number;
13
+ [key: string]: unknown;
14
+ };
15
+ export interface ShellLayoutProvider {
16
+ getLayout: () => Layout | null;
17
+ applyLayout: (layout: Layout, options?: {
18
+ name?: string;
19
+ }) => Promise<{
20
+ skipped: string[];
21
+ }>;
22
+ }
23
+ export declare function setShellCallbacks(next: TabShellCallbacks | null): void;
24
+ export declare function setShellLayoutProvider(next: ShellLayoutProvider | null): void;
25
+ export declare function setShellHosts(next: Host[], loaded?: boolean): void;
26
+ export declare function useShellHosts(): {
27
+ hosts: Host[];
28
+ loaded: boolean;
29
+ };
30
+ export declare function notifyTabsChanged(): void;
31
+ /** Called once the shell has restored its tabs. Late listeners fire at once. */
32
+ export declare function notifyShellReady(): void;
33
+ /**
34
+ * A plugin hands back the typed record it got from the SDK, which carries
35
+ * fewer fields than the shell's own host. A tab should get the shell's host,
36
+ * with whatever the plugin set on top.
37
+ */
38
+ export declare function withShellHost(host: Host | null): Host | null;
39
+ /** The shell's own copy of a saved host, with every plugin's settings. */
40
+ export declare function shellHost(id: string | number | undefined): Host | undefined;
41
+ /** Forwards to the mounted shell; a no-op before it mounts or after logout. */
42
+ export declare const shell: TabShellCallbacks;
43
+ export declare const tabsApi: {
44
+ openTab: (host: Host | null, type: string, options?: {
45
+ label?: string;
46
+ forceNewTab?: boolean;
47
+ data?: Record<string, unknown>;
48
+ }) => void;
49
+ openSingletonTab: (type: string, options?: {
50
+ label?: string;
51
+ data?: Record<string, unknown>;
52
+ }) => void;
53
+ connectHost: (host: Host, type?: string) => void;
54
+ closeTab: (tabId: string) => void;
55
+ openRailView: (id: string) => void;
56
+ getLayout: () => Layout;
57
+ applyLayout: (layout: Layout, options?: {
58
+ name?: string;
59
+ }) => Promise<{
60
+ skipped: string[];
61
+ }>;
62
+ onChange: (listener: () => void) => () => void;
63
+ onReady: (listener: () => void) => () => void;
64
+ };
65
+ /** Test seam, and on logout. */
66
+ export declare function resetShellBridge(): void;
67
+ export {};
@@ -0,0 +1,31 @@
1
+ import { type PluginRecord } from "./plugin-store";
2
+ /**
3
+ * Who owns a tab type, rail view or dashboard card.
4
+ *
5
+ * Read from the manifests in GET /plugins rather than from what registered,
6
+ * because a disabled plugin never runs its frontend and so never registers
7
+ * anything, yet a saved tab or card of its still has to say whose it is.
8
+ */
9
+ export type ViewKind = "tab" | "panel" | "card";
10
+ export type ViewStatus =
11
+ /** Registered by a running plugin. */
12
+ "ready"
13
+ /** Owner is enabled but its frontend has not finished loading. */
14
+ | "loading"
15
+ /** Owner is installed but switched off. */
16
+ | "disabled"
17
+ /** Owner's frontend or backend failed, or a hard dependency is missing. */
18
+ | "failed"
19
+ /** Nobody we know of declares this view. */
20
+ | "missing";
21
+ export declare function viewOwner(kind: ViewKind, id: string): PluginRecord | undefined;
22
+ /** Whether a manifest declares the id, i.e. the plugin may register it. */
23
+ export declare function manifestDeclares(contributes: PluginRecord["summary"]["contributes"], kind: ViewKind, id: string): boolean;
24
+ /**
25
+ * Status of a view that is NOT currently registered. Callers check their
26
+ * registry first; this explains why it is absent.
27
+ */
28
+ export declare function unregisteredViewStatus(kind: ViewKind, id: string): {
29
+ status: Exclude<ViewStatus, "ready">;
30
+ owner?: PluginRecord;
31
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Host editor sections contributed by plugins.
3
+ *
4
+ * A plugin declares host-scope fields in its manifest and core draws them, so
5
+ * a plugin cannot ship its own form styling and a section disappears when its
6
+ * plugin does. The enable switch comes first and gates the rest, which is the
7
+ * shape the hardcoded feature tabs already have.
8
+ *
9
+ * Nothing is rendered when no enabled plugin declares host settings, so the
10
+ * group does not appear as an empty tab.
11
+ */
12
+ import { type PluginSummary } from "../api/plugins-api";
13
+ /** Values for every plugin on one host: { [pluginId]: { [key]: value } }. */
14
+ export type HostPluginSettings = Record<string, Record<string, unknown>>;
15
+ /** Enabled plugins declaring host-scope settings. */
16
+ export declare function usePluginHostSections(): PluginSummary[];
17
+ export interface HostPluginSectionsProps {
18
+ plugins: PluginSummary[];
19
+ values: HostPluginSettings;
20
+ setValue: (pluginId: string, key: string, value: unknown) => void;
21
+ }
22
+ export declare function HostPluginSections({ plugins, values, setValue, }: HostPluginSectionsProps): import("react").JSX.Element;
23
+ export interface HostFeatureFieldsProps {
24
+ form: any;
25
+ updateForm: (patch: (form: Record<string, unknown>) => Record<string, unknown>) => void;
26
+ }
27
+ /**
28
+ * The calling plugin's manifest host settings, for a plugin that registered
29
+ * its own host editor section and so gets no generated tab.
30
+ */
31
+ export declare function HostFeatureFields({ form, updateForm, }: HostFeatureFieldsProps): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * One control per declared settings field type.
3
+ *
4
+ * A plugin supplies data; core draws the form. That is what keeps every
5
+ * plugin's settings page looking like the rest of the app, and what makes a
6
+ * page disappear cleanly when its plugin does.
7
+ */
8
+ import { type PluginSettingsField } from "../api/plugins-api";
9
+ export interface SettingsFieldProps {
10
+ pluginId: string;
11
+ field: PluginSettingsField;
12
+ values: Record<string, unknown>;
13
+ setValue: (key: string, value: unknown) => void;
14
+ /** Whether the owning plugin is running. */
15
+ running: boolean;
16
+ /** Message from a rejected save, shown under the control. */
17
+ error?: string;
18
+ disabled?: boolean;
19
+ /** In the host editor, the host default this field is ("pluginId.key"). */
20
+ defaultKey?: string;
21
+ }
22
+ export declare function SettingsFieldRow({ pluginId, field, values, setValue, running, error, disabled, defaultKey, }: SettingsFieldProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Gives every feature with manifest-declared host settings its own host editor
3
+ * tab, named after the feature. A plugin that registered its own host editor
4
+ * section already edits its settings there, so it gets no generated tab.
5
+ *
6
+ * Re-run whenever the plugin list changes so tabs come and go without a reload.
7
+ */
8
+ import type { PluginSummary } from "../api/plugins-api";
9
+ export declare function hostFeatureTabId(pluginId: string): string;
10
+ /** Adds, updates and removes generated tabs to match the plugin list. */
11
+ export declare function syncHostFeatureTabs(plugins: PluginSummary[]): string[];
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Components behind a `type: "custom"` settings field.
3
+ *
4
+ * Most settings are expressible as a schema, and those are rendered from the
5
+ * manifest so a plugin cannot ship its own form styling. A few are not: a
6
+ * device browser, a provider list. Those declare a component id here instead,
7
+ * which keeps the escape hatch narrow and named rather than letting a plugin
8
+ * hand core arbitrary markup. A plugin registers them from its frontend
9
+ * through `app.registerSettingsComponent`.
10
+ */
11
+ import type { ComponentType } from "react";
12
+ export interface SettingsComponentProps {
13
+ pluginId: string;
14
+ /** Current values for the scope this field sits in. */
15
+ values: Record<string, unknown>;
16
+ /** Writes one key in the same scope. */
17
+ setValue: (key: string, value: unknown) => void;
18
+ /** Whether the owning plugin is running. */
19
+ running: boolean;
20
+ }
21
+ export type SettingsComponent = ComponentType<SettingsComponentProps>;
22
+ export declare function registerSettingsComponent(pluginId: string, componentId: string, component: SettingsComponent): () => void;
23
+ export declare function getSettingsComponent(pluginId: string, componentId: string | undefined): SettingsComponent | undefined;
24
+ /** Registered "<pluginId>:<componentId>" keys. */
25
+ export declare function listSettingsComponents(): string[];
26
+ /** Re-renders when components are registered, e.g. after a plugin loads. */
27
+ export declare const useSettingsComponents: () => {
28
+ id: string;
29
+ component: SettingsComponent;
30
+ }[];
31
+ /** Test helper. */
32
+ export declare function resetSettingsComponents(): void;
@@ -0,0 +1,11 @@
1
+ import type { PluginSettingsField } from "../api/plugins-api";
2
+ /**
3
+ * Whether the generic form draws a field: not hidden (the plugin edits it in
4
+ * its own UI) and its `requires` gate satisfied.
5
+ *
6
+ * Kept out of the component file so both the settings page and the host editor
7
+ * section can import it without dragging a component along.
8
+ */
9
+ export declare function isFieldShown(field: PluginSettingsField, values: Record<string, unknown>): boolean;
10
+ /** Whether a plugin has any field the generic form would ever draw. */
11
+ export declare function hasVisibleFields(fields: PluginSettingsField[]): boolean;
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ import { type SlotContribution } from "./action-registry";
3
+ interface ActionSlotProps {
4
+ slotId: string;
5
+ /**
6
+ * Arguments for the action, read at click time rather than on render. A
7
+ * getter keeps expensive context (a serialized terminal buffer, say) off the
8
+ * render path.
9
+ */
10
+ context?: () => unknown[];
11
+ /** Applied to the default button so a slot owner can match its own controls. */
12
+ className?: string;
13
+ /** Hides the whole slot. For a surface that is contextually unavailable. */
14
+ enabled?: boolean;
15
+ /** Renders a contribution the owner's own way instead of as a button. */
16
+ renderItem?: (contribution: SlotContribution, invoke: () => void) => React.ReactNode;
17
+ /** Icon-only, for toolbars that collapse their labels. */
18
+ hideLabels?: boolean;
19
+ /** Passed to each contribution's `when`. */
20
+ when?: Record<string, unknown>;
21
+ }
22
+ /**
23
+ * Renders whatever plugins have contributed to a named slot.
24
+ *
25
+ * Renders null when there is nothing to show, which covers both "no plugin
26
+ * contributed" and "the user may not see what was contributed". Those two
27
+ * cases are deliberately identical in the DOM: no placeholder, no disabled
28
+ * button, nothing hinting at a feature the user cannot reach.
29
+ */
30
+ export declare function ActionSlot({ slotId, context, className, enabled, renderItem, hideLabels, when, }: ActionSlotProps): React.JSX.Element;
31
+ /**
32
+ * Renders the component contributions in a slot, each with the owner's
33
+ * props. Same permission and `when` filtering as buttons, and the same
34
+ * nothing-at-all output when there is nothing to show.
35
+ */
36
+ export declare function ComponentSlot({ slotId, props, when, }: {
37
+ slotId: string;
38
+ props?: Record<string, unknown>;
39
+ when?: Record<string, unknown>;
40
+ }): React.JSX.Element;
41
+ export {};
@@ -0,0 +1,30 @@
1
+ import React, { type ReactNode } from "react";
2
+ import type { TabContextTab } from "../../types/index";
3
+ export type Tab = TabContextTab;
4
+ interface TabContextType {
5
+ tabs: Tab[];
6
+ currentTab: number | null;
7
+ allSplitScreenTab: number[];
8
+ addTab: (tab: Omit<Tab, "id">) => number;
9
+ removeTab: (tabId: number) => void;
10
+ setCurrentTab: (tabId: number) => void;
11
+ setSplitScreenTab: (tabId: number) => void;
12
+ getTab: (tabId: number) => Tab | undefined;
13
+ reorderTabs: (fromIndex: number, toIndex: number) => void;
14
+ updateHostConfig: (hostId: number, newHostConfig: {
15
+ id: number;
16
+ name?: string;
17
+ username: string;
18
+ ip: string;
19
+ port: number;
20
+ }) => void;
21
+ updateTab: (tabId: number, updates: Partial<Omit<Tab, "id">>) => void;
22
+ }
23
+ export declare function useTabs(): TabContextType;
24
+ export declare function useTabsSafe(): TabContextType;
25
+ interface TabProviderProps {
26
+ children: ReactNode;
27
+ }
28
+ export declare function clearTermixSessionStorage(): void;
29
+ export declare function TabProvider({ children }: TabProviderProps): React.JSX.Element;
30
+ export {};
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Runtime registry for plugin-contributed UI actions and the slots they fill.
3
+ *
4
+ * This is the frontend sibling of src/backend/plugins/service-registry.ts, and
5
+ * the difference between them is the thing to be clear about:
6
+ *
7
+ * - The backend registry's proxy IS a boundary. It checks the acting user's
8
+ * RBAC permission on every call before the provider ever runs.
9
+ * - This one is NOT. It runs in the browser, where anyone can call
10
+ * invokeAction from the console. The permission attached to an action
11
+ * decides whether a button is DRAWN, nothing more.
12
+ *
13
+ * Real enforcement stays where it already is: the backend route the handler
14
+ * eventually calls. Treating this file as a security boundary is the easy
15
+ * mistake to make when reading the two side by side, so it is said plainly
16
+ * here rather than left to be inferred.
17
+ *
18
+ * Unlike the rail and tab registries (rail-items.ts, tabUtils.tsx), which are
19
+ * plain Maps read during render, this one is reactive. A slot renders live and
20
+ * has to react when a plugin is enabled or disabled at runtime, so it carries
21
+ * subscribe/getSnapshot plumbing for useSyncExternalStore.
22
+ */
23
+ import type { ComponentType } from "react";
24
+ /**
25
+ * Args are unknown[] because the registry never inspects them: a slot owner
26
+ * passes whatever its surface offers (the terminal passes its buffer text) and
27
+ * the contributing plugin knows what to expect. Handlers are written with
28
+ * concrete parameter types, so registerAction accepts those too.
29
+ */
30
+ export type ActionHandler = (...args: never[]) => unknown;
31
+ export interface RegisteredAction {
32
+ id: string;
33
+ handler: ActionHandler;
34
+ /** Role permission a user needs before this action is offered. */
35
+ permission?: string;
36
+ pluginId?: string;
37
+ }
38
+ export interface ActionSlotDefinition {
39
+ id: string;
40
+ /** Contribution kinds this slot will render. */
41
+ accepts: string[];
42
+ }
43
+ export interface SlotContribution {
44
+ /** Action invoked when this contribution is activated. */
45
+ actionId: string;
46
+ titleKey: string;
47
+ /** Secondary text, for slots that show one (onboarding cards). */
48
+ descriptionKey?: string;
49
+ icon?: ComponentType<{
50
+ className?: string;
51
+ }>;
52
+ /** Checked against the slot's accepts. Defaults to "button". */
53
+ kind?: string;
54
+ /**
55
+ * For kind "component": rendered by the slot owner with its own props,
56
+ * e.g. a panel docked into the terminal.
57
+ */
58
+ component?: ComponentType<Record<string, unknown>>;
59
+ /** Extra condition, evaluated against the slot owner's context. */
60
+ when?: (context: Record<string, unknown>) => boolean;
61
+ pluginId?: string;
62
+ /** Lower sorts first. Ties break on actionId so ordering is stable. */
63
+ order?: number;
64
+ }
65
+ export declare function registerAction(id: string, handler: ActionHandler, options?: {
66
+ permission?: string;
67
+ pluginId?: string;
68
+ }): () => void;
69
+ /** Every registered action. */
70
+ export declare function listActions(): RegisteredAction[];
71
+ /** Whether a handler is registered, i.e. its plugin is running. */
72
+ export declare function isActionRegistered(id: string): boolean;
73
+ /** The permission gating an action, if it declared one. */
74
+ export declare function getActionPermission(id: string): string | undefined;
75
+ /**
76
+ * Runs an action. Resolves quietly when the id is unknown: a contribution can
77
+ * outlive the plugin that registered its handler, and a click should not throw
78
+ * into the React event handler because of it.
79
+ */
80
+ export declare function invokeAction(id: string, ...args: unknown[]): Promise<unknown>;
81
+ export declare function declareActionSlot(slot: ActionSlotDefinition): () => void;
82
+ /**
83
+ * Adds a contribution to a slot.
84
+ *
85
+ * A contribution for a slot nobody has declared yet is kept rather than
86
+ * dropped: plugin activation order is not guaranteed, and the slot owner may
87
+ * register after the contributor. It becomes visible once the slot appears.
88
+ */
89
+ export declare function registerSlotContribution(slotId: string, contribution: SlotContribution): () => void;
90
+ export declare function unregisterSlotContribution(slotId: string, actionId: string): void;
91
+ /**
92
+ * Contributions for a slot, sorted and referentially stable between changes.
93
+ * Unfiltered: callers that render go through useActionSlot, which drops the
94
+ * ones the current user may not see.
95
+ */
96
+ export declare function getSlotContributions(slotId: string): SlotContribution[];
97
+ export declare function subscribeToActionRegistry(listener: () => void): () => void;
98
+ /** Test seam, mirroring resetPluginState(). */
99
+ export declare function resetActionRegistry(): void;
@@ -0,0 +1,62 @@
1
+ import type { ComponentType } from "react";
2
+ import type { KeybindingAction, KeyCombo } from "../../types/keybindings";
3
+ export interface KeybindingEditorProps {
4
+ action: KeybindingAction;
5
+ onChange: (action: KeybindingAction) => void;
6
+ }
7
+ export interface KeybindingRunContext {
8
+ sessionId?: string;
9
+ host?: {
10
+ ip?: string;
11
+ username?: string;
12
+ port?: number | string;
13
+ name?: string;
14
+ } | null;
15
+ send?: (data: string) => void;
16
+ }
17
+ /**
18
+ * An action a key can be bound to. The shell registers its own; plugins add
19
+ * theirs with app.registerKeybindingAction. `id` is what a saved binding
20
+ * stores as action.type.
21
+ */
22
+ export interface KeybindingActionDef {
23
+ id: string;
24
+ pluginId?: string;
25
+ /** A full translation key. */
26
+ labelKey: string;
27
+ scope: "session" | "global";
28
+ editor?: ComponentType<KeybindingEditorProps>;
29
+ summary?: ComponentType<KeybindingEditorProps>;
30
+ /** A full translation key when the action cannot be saved yet. */
31
+ validate?: (action: KeybindingAction) => string | null;
32
+ run?: (action: KeybindingAction, context: KeybindingRunContext) => void;
33
+ order?: number;
34
+ }
35
+ /** A built-in key the user can rebind. */
36
+ export interface KeybindingDefaultDef {
37
+ id: string;
38
+ pluginId?: string;
39
+ combo: KeyCombo;
40
+ /** A full translation key. */
41
+ descriptionKey: string;
42
+ order?: number;
43
+ }
44
+ /** Fired for the shell's own actions; AppShell runs them. */
45
+ export declare const GLOBAL_KEYBINDING_EVENT = "termix:global-keybinding";
46
+ export declare const SHELL_KEYBINDING_ACTION_IDS: string[];
47
+ /** Adds a plugin's action. A shell action's id cannot be taken over. */
48
+ export declare function registerKeybindingAction(action: KeybindingActionDef): () => void;
49
+ export declare const registerKeybindingDefault: (item: KeybindingDefaultDef) => () => void;
50
+ export declare const listKeybindingActions: () => KeybindingActionDef[];
51
+ export declare const useKeybindingActions: () => KeybindingActionDef[];
52
+ export declare const getKeybindingAction: (id: string) => KeybindingActionDef;
53
+ export declare const listKeybindingDefaults: () => KeybindingDefaultDef[];
54
+ export declare const useKeybindingDefaults: () => KeybindingDefaultDef[];
55
+ /** Back to the shell's own actions and no defaults, for tests. */
56
+ export declare function resetKeybindingRegistry(): void;
57
+ /**
58
+ * Runs a bound action through whoever registered it. False when nothing
59
+ * running handles its type (its plugin is off), so the caller can let the
60
+ * key through.
61
+ */
62
+ export declare function runKeybindingAction(action: KeybindingAction, context?: KeybindingRunContext): boolean;
@@ -0,0 +1,55 @@
1
+ import type { ComponentType } from "react";
2
+ import type { Host, Tab } from "../../types/ui-types";
3
+ import type { TabShellCallbacks } from "./tab-registry";
4
+ /** A command palette entry a plugin contributes. */
5
+ export interface PaletteEntryDef {
6
+ id: string;
7
+ pluginId?: string;
8
+ titleKey: string;
9
+ icon?: ComponentType<{
10
+ className?: string;
11
+ }>;
12
+ keywords?: string[];
13
+ scope: "global" | "host";
14
+ when?: (host?: Host) => boolean;
15
+ run: (shell: TabShellCallbacks, host?: Host) => void;
16
+ order?: number;
17
+ }
18
+ export declare const registerPaletteEntry: (item: PaletteEntryDef) => () => void;
19
+ export declare const usePaletteEntries: () => PaletteEntryDef[];
20
+ export declare const listPaletteEntries: () => PaletteEntryDef[];
21
+ export declare const resetPaletteEntries: () => void;
22
+ export declare function paletteEntriesFor(all: PaletteEntryDef[], scope: PaletteEntryDef["scope"], host?: Host): PaletteEntryDef[];
23
+ /** One row of a palette group. */
24
+ export interface PaletteItemDef {
25
+ id: string;
26
+ title: string;
27
+ description?: string;
28
+ icon?: ComponentType<{
29
+ className?: string;
30
+ }>;
31
+ keywords?: string[];
32
+ needsTarget?: boolean;
33
+ hint?: string;
34
+ run: (context: {
35
+ targetTab?: Tab;
36
+ shell: TabShellCallbacks;
37
+ }) => void;
38
+ }
39
+ /** A searchable group of items a plugin fills, e.g. its saved commands. */
40
+ export interface PaletteGroupDef {
41
+ id: string;
42
+ pluginId?: string;
43
+ titleKey: string;
44
+ order?: number;
45
+ load: () => PaletteItemDef[] | Promise<PaletteItemDef[]>;
46
+ showWhenEmpty?: boolean;
47
+ }
48
+ export declare const registerPaletteGroup: (item: PaletteGroupDef) => () => void;
49
+ export declare const usePaletteGroups: () => PaletteGroupDef[];
50
+ export declare const listPaletteGroups: () => PaletteGroupDef[];
51
+ export declare const resetPaletteGroups: () => void;
52
+ /** A group's items, or none when its loader throws. */
53
+ export declare function loadPaletteGroup(group: PaletteGroupDef): Promise<PaletteItemDef[]>;
54
+ /** The items the query matches, by title, description or keyword. */
55
+ export declare function filterPaletteItems(items: PaletteItemDef[], query: string, showWhenEmpty?: boolean): PaletteItemDef[];
@@ -0,0 +1,24 @@
1
+ import type { ComponentType } from "react";
2
+ import type { TabShellCallbacks } from "./tab-registry";
3
+ export interface PanelRenderProps {
4
+ /** The command-target tab the user is working in, if any. */
5
+ targetTab?: import("../../types/ui-types").Tab;
6
+ active: boolean;
7
+ shell: TabShellCallbacks;
8
+ setEditing: (editing: boolean) => void;
9
+ activeTabType?: string;
10
+ placement: "left" | "right" | "tab";
11
+ }
12
+ /** Sidebar content for a rail view a plugin contributes. */
13
+ export interface PanelDef {
14
+ id: string;
15
+ pluginId?: string;
16
+ component: ComponentType<PanelRenderProps>;
17
+ /** Stays mounted once opened, so its state survives switching away. */
18
+ keepMounted?: boolean;
19
+ }
20
+ export declare const registerPanel: (item: PanelDef) => () => void;
21
+ export declare const getPanel: (id: string) => PanelDef;
22
+ export declare const listPanels: () => PanelDef[];
23
+ export declare const usePanels: () => PanelDef[];
24
+ export declare const resetPanels: () => void;
@@ -0,0 +1,92 @@
1
+ import type { ConfirmOptions } from "../components/surface/surface-scope";
2
+ import type { ComponentType, Ref } from "react";
3
+ import type { HostDraft } from "@termix-ssh/plugin-sdk/frontend";
4
+ import type { Host, Tab } from "../../types/ui-types";
5
+ /**
6
+ * The shell callbacks a registered tab may use. Same bag every tab gets, so
7
+ * a plugin tab can do anything a core tab can without new positional props.
8
+ */
9
+ export interface TabShellCallbacks {
10
+ openTab: (host: Host | null, type: string, options?: {
11
+ label?: string;
12
+ forceNewTab?: boolean;
13
+ data?: Record<string, unknown>;
14
+ }) => void;
15
+ openSingletonTab: (type: string, options?: {
16
+ label?: string;
17
+ data?: Record<string, unknown>;
18
+ }) => void;
19
+ /** Connects the way clicking the host in the host list does. */
20
+ connectHost: (host: Host, type?: string) => void;
21
+ closeTab: (tabId: string) => void;
22
+ renameTab: (tabId: string, label: string) => void;
23
+ openRailView: (id: string) => void;
24
+ /** Closes a rail view wherever it is shown, e.g. when its feature goes away. */
25
+ closeRailView: (id: string) => void;
26
+ /** Opens the host editor for a new host with these fields filled in. */
27
+ openHostEditor?: (draft?: HostDraft) => void;
28
+ /** Saves a quick-connect tab's host. Core terminal only. */
29
+ saveQuickConnect?: (tab: Tab, host: Host) => Promise<void>;
30
+ /** Asks a yes or no question over the main area. */
31
+ confirm?: (options: ConfirmOptions) => Promise<boolean>;
32
+ }
33
+ export interface TabRenderProps {
34
+ tab: Tab;
35
+ host?: Host;
36
+ /** The host in the shape SSH-facing components take. */
37
+ sshHost?: Record<string, unknown>;
38
+ label: string;
39
+ isVisible: boolean;
40
+ isFocusedPane: boolean;
41
+ inSplit?: boolean;
42
+ handleRef: Ref<unknown>;
43
+ shell: TabShellCallbacks;
44
+ }
45
+ export interface StandaloneViewProps {
46
+ hostId?: string;
47
+ view: string;
48
+ params: URLSearchParams;
49
+ }
50
+ export interface TabTypeDef {
51
+ /** The tab type. */
52
+ id: string;
53
+ pluginId?: string;
54
+ component: ComponentType<TabRenderProps>;
55
+ icon?: ComponentType<{
56
+ className?: string;
57
+ }>;
58
+ titleKey?: string;
59
+ requiresHost?: boolean;
60
+ noHostMessageKey?: string;
61
+ persistent?: boolean;
62
+ singleton?: boolean;
63
+ session?: boolean;
64
+ hostless?: boolean;
65
+ restore?: (host: Host) => boolean;
66
+ activityTypes?: string[];
67
+ standalone?: ComponentType<StandaloneViewProps>;
68
+ standaloneViews?: string[];
69
+ panelFrame?: boolean;
70
+ /** False keeps this tab out of saved layouts and workspaces. */
71
+ inLayouts?: boolean;
72
+ /** Panels that type into a terminal act on the last one of these focused. */
73
+ commandTarget?: boolean;
74
+ /** Paints its own background; its frame stays transparent. */
75
+ ownBackground?: boolean;
76
+ /** Every open is a new tab. */
77
+ multiInstance?: boolean;
78
+ preload?: () => Promise<unknown>;
79
+ }
80
+ export declare const registerTabType: (item: TabTypeDef) => () => void;
81
+ export declare const getTabType: (id: string) => TabTypeDef;
82
+ export declare const listTabTypes: () => TabTypeDef[];
83
+ export declare const useTabTypes: () => TabTypeDef[];
84
+ export declare const resetTabTypes: () => void;
85
+ export declare function isPersistentTabType(type: string): boolean;
86
+ export declare function isSessionTabType(type: string): boolean;
87
+ /** Whether a saved tab of this type may be restored for this host. */
88
+ export declare function canRestoreTabType(type: string, host: Host | undefined): boolean;
89
+ /** The tab type a recent-activity entry opens, if a registered tab claims it. */
90
+ export declare function tabTypeForActivity(activityType: string): TabTypeDef | undefined;
91
+ /** The registered tab serving a `?view=` full-screen link. */
92
+ export declare function standaloneViewFor(view: string): TabTypeDef | undefined;