@termix-ssh/plugin-sdk 1.0.23 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.25
4
+
5
+ Plugin API 1.14.0.
6
+
7
+ ### Added
8
+
9
+ - Host click behavior `hostPage` opens a host page when a plugin offers one
10
+ - `createApiKey` takes scopes, to limit a key to actions
11
+
12
+ ## 1.0.24
13
+
14
+ Plugin API 1.14.0.
15
+
16
+ ### Added
17
+
18
+ - `app.registerHostSection` adds a card to the host page
19
+ - `/ui` exports `HostTabEmbed`, which draws any tab type inside another view, the host section registry, and `operationsApi` for core's `/operations` routes
20
+
3
21
  ## 1.0.23
4
22
 
5
23
  Plugin API 1.14.0.
package/PLUGIN-GUIDE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Termix plugin guide
2
2
 
3
- SDK 1.0.23 | Plugin API 1.14.0
3
+ SDK 1.0.25 | Plugin API 1.14.0
4
4
 
5
5
  This guide is for anyone, person or AI coding tool, building a Termix plugin. It ships inside
6
6
  `@termix-ssh/plugin-sdk`, so the copy in your `node_modules` always matches the SDK you have installed.
@@ -643,6 +643,20 @@ export interface HostBadgeContribution {
643
643
  export type HostStatusIndicatorContribution = HostBadgeContribution;
644
644
  /** A control in the host editor's toolbar. */
645
645
  export type HostEditorToolbarItemContribution = HostBadgeContribution;
646
+ export interface HostSectionProps {
647
+ host: PluginHostRecord;
648
+ isVisible: boolean;
649
+ shell: ShellApi;
650
+ }
651
+ export interface HostSectionContribution {
652
+ /** Declare it in manifest contributes.hostSections too. */
653
+ id: string;
654
+ titleKey: string;
655
+ /** Lower sorts first. */
656
+ order?: number;
657
+ when?: (host: PluginHostRecord) => boolean;
658
+ component: ComponentType<HostSectionProps>;
659
+ }
646
660
  export interface HostContextMenuItemContribution {
647
661
  id: string;
648
662
  titleKey: string;
@@ -1085,6 +1099,11 @@ export interface TermixApp extends TermixAppInfo {
1085
1099
  /** Adds a control to the host editor's toolbar. */
1086
1100
  registerHostEditorToolbarItem: (item: HostEditorToolbarItemContribution) => Disposer;
1087
1101
  registerHostContextMenuItem: (item: HostContextMenuItemContribution) => Disposer;
1102
+ /**
1103
+ * A card on the host page. Core 26.11.1 and newer; call it as
1104
+ * app.registerHostSection?.(...) if your plugin allows older cores.
1105
+ */
1106
+ registerHostSection: (section: HostSectionContribution) => Disposer;
1088
1107
  registerPaletteEntry: (entry: PaletteEntryContribution) => Disposer;
1089
1108
  registerPaletteGroup: (group: PaletteGroupContribution) => Disposer;
1090
1109
  registerKeybindingAction: (action: KeybindingActionContribution) => Disposer;
@@ -29,7 +29,7 @@ import {
29
29
  sortPlugins,
30
30
  uploadEntry,
31
31
  youtubeEmbedUrl
32
- } from "./chunk-C52NRTA6.js";
32
+ } from "./chunk-ENDXPKBA.js";
33
33
  import {
34
34
  Button,
35
35
  FakeSwitch,
@@ -37,7 +37,7 @@ import {
37
37
  PluginIcon,
38
38
  SectionCard,
39
39
  hasSettingsPage
40
- } from "./chunk-IMPLAAUM.js";
40
+ } from "./chunk-WAPKSDXJ.js";
41
41
  import {
42
42
  ArrowDownWideNarrow,
43
43
  BookOpen,
@@ -109,8 +109,8 @@ import {
109
109
  updatePlugin,
110
110
  uploadPlugin,
111
111
  useConfirm
112
- } from "./chunk-DN6YKMFJ.js";
113
- import "./chunk-6WLECSNB.js";
112
+ } from "./chunk-GVJBUCYJ.js";
113
+ import "./chunk-DUOTWQ4Y.js";
114
114
  import {
115
115
  __toESM,
116
116
  define_import_meta_env_default,
@@ -26,7 +26,7 @@ var inFlight = null;
26
26
  function load() {
27
27
  if (cache) return Promise.resolve(cache);
28
28
  if (inFlight) return inFlight;
29
- inFlight = import("./rbac-api-A64TXDL5.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
29
+ inFlight = import("./rbac-api-NXDICNA4.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
30
30
  cache = {
31
31
  permissions: result.permissions ?? [],
32
32
  isAdmin: !!result.isAdmin
@@ -5196,7 +5196,8 @@ var TRAY_TRIGGERS = [
5196
5196
  var HOST_CLICK_BEHAVIORS = [
5197
5197
  "newTab",
5198
5198
  "focusExisting",
5199
- "focusExistingDoubleClickNew"
5199
+ "focusExistingDoubleClickNew",
5200
+ "hostPage"
5200
5201
  ];
5201
5202
  var STATUS_COLOR_SCHEMES = ["accent", "status"];
5202
5203
  var FILTER_STATUS = [
@@ -5715,12 +5716,13 @@ async function revokeAllUserSessions(userId) {
5715
5716
  handleApiError(error, "revoke all user sessions");
5716
5717
  }
5717
5718
  }
5718
- async function createApiKey(name, userId, expiresAt) {
5719
+ async function createApiKey(name, userId, expiresAt, scopes) {
5719
5720
  try {
5720
5721
  const response = await authApi.post("/users/api-keys", {
5721
5722
  name,
5722
5723
  userId,
5723
- expiresAt: expiresAt ?? null
5724
+ expiresAt: expiresAt ?? null,
5725
+ scopes: scopes?.length ? scopes : null
5724
5726
  });
5725
5727
  return response.data;
5726
5728
  } catch (error) {
@@ -6340,7 +6342,7 @@ async function updateRole(roleId, roleData) {
6340
6342
  try {
6341
6343
  const response = await rbacApi.put(`/rbac/roles/${roleId}`, roleData);
6342
6344
  if (roleData.permissions) {
6343
- const { notifyPermissionsChanged } = await import("./use-permissions-FLQAN6I7.js");
6345
+ const { notifyPermissionsChanged } = await import("./use-permissions-MHDIU67P.js");
6344
6346
  notifyPermissionsChanged();
6345
6347
  }
6346
6348
  return response.data;
@@ -6947,7 +6949,7 @@ function createRemoteOriginApiInstance(path) {
6947
6949
  });
6948
6950
  instance.interceptors.request.use(
6949
6951
  async (config) => {
6950
- const { getLinkedSession: getLinkedSession2 } = await import("./linked-server-YCAJ2NX3.js");
6952
+ const { getLinkedSession: getLinkedSession2 } = await import("./linked-server-2HT4BRH4.js");
6951
6953
  const linked = await getLinkedSession2();
6952
6954
  config.baseURL = linked ? `${linked.serverUrl}${path}` : "http://no-server-configured";
6953
6955
  if (config.headers.set) {
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  Button
4
- } from "./chunk-IMPLAAUM.js";
4
+ } from "./chunk-WAPKSDXJ.js";
5
5
  import {
6
6
  ChevronRight,
7
7
  PANEL,
@@ -10,10 +10,10 @@ import {
10
10
  cn,
11
11
  gridSizeStyle,
12
12
  useAreaPreferences
13
- } from "./chunk-DN6YKMFJ.js";
13
+ } from "./chunk-GVJBUCYJ.js";
14
14
  import {
15
15
  isElectron
16
- } from "./chunk-6WLECSNB.js";
16
+ } from "./chunk-DUOTWQ4Y.js";
17
17
  import {
18
18
  __commonJS,
19
19
  __toESM,
@@ -3,7 +3,7 @@ import {
3
3
  hasPermission,
4
4
  resetPermissionsCache,
5
5
  usePermissions
6
- } from "./chunk-GRH7GSKG.js";
6
+ } from "./chunk-D45W5IDI.js";
7
7
  import {
8
8
  Columns2,
9
9
  KeyRound,
@@ -51,7 +51,7 @@ import {
51
51
  withIconBoundary,
52
52
  withPluginContext,
53
53
  withPluginScope
54
- } from "./chunk-DN6YKMFJ.js";
54
+ } from "./chunk-GVJBUCYJ.js";
55
55
  import {
56
56
  SYNC_CHANGED_EVENT,
57
57
  TRUST_TOKEN_KEY,
@@ -99,7 +99,7 @@ import {
99
99
  usePluginStore,
100
100
  useTabTypes,
101
101
  websocketAuthProtocols
102
- } from "./chunk-6WLECSNB.js";
102
+ } from "./chunk-DUOTWQ4Y.js";
103
103
  import {
104
104
  init_define_import_meta_env
105
105
  } from "./chunk-YGYBM7SQ.js";
@@ -1405,6 +1405,7 @@ var en_default = {
1405
1405
  hostClickBehavior: "Clicking a host",
1406
1406
  hostClickBehaviorDesc: 'What happens when you click a host that already has an open tab. Ctrl/Cmd click, middle click, or "Open in new tab" always start a new one.',
1407
1407
  hostClickNewTab: "Always open a new tab",
1408
+ hostClickHostPage: "Open the host page, when a plugin offers one",
1408
1409
  hostClickFocusExisting: "Switch to the open tab",
1409
1410
  hostClickFocusExistingDoubleNew: "Click to switch, double click for a new tab",
1410
1411
  openInNewTab: "Open in new tab",
@@ -3060,6 +3061,23 @@ function withProtocolSettings(pluginSettings, flags, list = listHostProtocols())
3060
3061
  return next;
3061
3062
  }
3062
3063
 
3064
+ // src/ui/shell/host-sections.ts
3065
+ init_define_import_meta_env();
3066
+ var sections2 = createRegistry(byOrderThenId);
3067
+ var registerHostSection = sections2.register;
3068
+ var useHostSections = sections2.useList;
3069
+ var listHostSections = sections2.list;
3070
+ var resetHostSections = sections2.reset;
3071
+ function hostSectionsFor(all, host) {
3072
+ return all.filter((section) => {
3073
+ try {
3074
+ return section.when(host);
3075
+ } catch {
3076
+ return false;
3077
+ }
3078
+ });
3079
+ }
3080
+
3063
3081
  // src/ui/dashboard/dashboard-cards-registry.ts
3064
3082
  init_define_import_meta_env();
3065
3083
  var registry3 = createRegistry();
@@ -3244,6 +3262,22 @@ function createPluginApi(pluginId) {
3244
3262
  }
3245
3263
  });
3246
3264
  }
3265
+ function createOperationsApi() {
3266
+ return new Proxy(authApi, {
3267
+ get(target, property, receiver) {
3268
+ const value = Reflect.get(target, property, receiver);
3269
+ if (typeof value !== "function") return value;
3270
+ if (property === "get" || property === "delete" || property === "post" || property === "put" || property === "patch") {
3271
+ return (url, ...rest) => value.call(
3272
+ target,
3273
+ `/operations${url.startsWith("/") ? url : `/${url}`}`,
3274
+ ...rest
3275
+ );
3276
+ }
3277
+ return value.bind(target);
3278
+ }
3279
+ });
3280
+ }
3247
3281
  function pluginFetch(pluginId, path2, init = {}) {
3248
3282
  const base = (authApi.defaults.baseURL ?? "").replace(/\/+$/, "");
3249
3283
  const headers = new Headers(init.headers);
@@ -8688,6 +8722,20 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
8688
8722
  })
8689
8723
  );
8690
8724
  },
8725
+ registerHostSection(section) {
8726
+ return track(
8727
+ registerHostSection({
8728
+ id: section.id,
8729
+ pluginId,
8730
+ titleKey: key(section.titleKey),
8731
+ order: section.order,
8732
+ when: hostCallback(section.when ?? (() => true)),
8733
+ component: scoped(
8734
+ section.component
8735
+ )
8736
+ })
8737
+ );
8738
+ },
8691
8739
  registerHostContextMenuItem(item) {
8692
8740
  return track(
8693
8741
  registerHostContextMenuItem({
@@ -9096,6 +9144,11 @@ export {
9096
9144
  hostProtocolFlags,
9097
9145
  enabledHostProtocols,
9098
9146
  withProtocolSettings,
9147
+ registerHostSection,
9148
+ useHostSections,
9149
+ listHostSections,
9150
+ resetHostSections,
9151
+ hostSectionsFor,
9099
9152
  registerDashboardCard,
9100
9153
  getRegisteredDashboardCard,
9101
9154
  registeredDashboardCardList,
@@ -9113,6 +9166,7 @@ export {
9113
9166
  registerSlotContribution,
9114
9167
  getSlotContributions,
9115
9168
  resetActionRegistry,
9169
+ createOperationsApi,
9116
9170
  pluginWsUrl,
9117
9171
  PluginComponent,
9118
9172
  onboardingSteps,
@@ -4,7 +4,7 @@ import {
4
4
  getPluginRecord,
5
5
  rbacApi,
6
6
  usePluginStore
7
- } from "./chunk-6WLECSNB.js";
7
+ } from "./chunk-DUOTWQ4Y.js";
8
8
  import {
9
9
  __export,
10
10
  init_define_import_meta_env
@@ -15,10 +15,10 @@ import {
15
15
  useCompanionState,
16
16
  useIsMobile,
17
17
  useSettingsComponents
18
- } from "./chunk-X65V7ZRW.js";
18
+ } from "./chunk-GTTGPAMQ.js";
19
19
  import {
20
20
  usePermissions
21
- } from "./chunk-GRH7GSKG.js";
21
+ } from "./chunk-D45W5IDI.js";
22
22
  import {
23
23
  Button,
24
24
  DefaultsOnly,
@@ -30,7 +30,7 @@ import {
30
30
  SettingRow,
31
31
  hasVisibleFields,
32
32
  isFieldShown
33
- } from "./chunk-IMPLAAUM.js";
33
+ } from "./chunk-WAPKSDXJ.js";
34
34
  import {
35
35
  ArrowDownToLine,
36
36
  ArrowLeftToLine,
@@ -61,12 +61,12 @@ import {
61
61
  pluginKey,
62
62
  pluginName,
63
63
  usePluginScope
64
- } from "./chunk-DN6YKMFJ.js";
64
+ } from "./chunk-GVJBUCYJ.js";
65
65
  import {
66
66
  getTabType,
67
67
  unregisteredViewStatus,
68
68
  usePluginStore
69
- } from "./chunk-6WLECSNB.js";
69
+ } from "./chunk-DUOTWQ4Y.js";
70
70
  import {
71
71
  init_define_import_meta_env
72
72
  } from "./chunk-YGYBM7SQ.js";
@@ -1321,7 +1321,7 @@ function CompanionLayout({
1321
1321
  // src/ui/shell/tabUtils.tsx
1322
1322
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1323
1323
  var PluginsTab = lazy(
1324
- () => import("./PluginsTab-MNQU5OJ3.js").then((m) => ({ default: m.PluginsTab }))
1324
+ () => import("./PluginsTab-NT64NFPK.js").then((m) => ({ default: m.PluginsTab }))
1325
1325
  );
1326
1326
  function preloadTabSurface(type) {
1327
1327
  const loader = getTabType(type)?.preload;
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  useTheme
4
- } from "./chunk-X65V7ZRW.js";
4
+ } from "./chunk-GTTGPAMQ.js";
5
5
  import {
6
6
  init_define_import_meta_env
7
7
  } from "./chunk-YGYBM7SQ.js";
@@ -9,7 +9,7 @@ import {
9
9
  icons_exports,
10
10
  isFieldActive,
11
11
  usePluginScope
12
- } from "./chunk-DN6YKMFJ.js";
12
+ } from "./chunk-GVJBUCYJ.js";
13
13
  import {
14
14
  init_define_import_meta_env
15
15
  } from "./chunk-YGYBM7SQ.js";
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  Toaster
4
- } from "./chunk-BP42N374.js";
4
+ } from "./chunk-QGWRLGQB.js";
5
5
  import {
6
6
  ThemeProvider,
7
7
  createPluginApp,
@@ -12,8 +12,8 @@ import {
12
12
  setPluginThemes,
13
13
  sshHostToHost,
14
14
  useTheme
15
- } from "./chunk-X65V7ZRW.js";
16
- import "./chunk-GRH7GSKG.js";
15
+ } from "./chunk-GTTGPAMQ.js";
16
+ import "./chunk-D45W5IDI.js";
17
17
  import {
18
18
  SurfaceScope,
19
19
  notifyShellReady,
@@ -21,13 +21,13 @@ import {
21
21
  setShellCallbacks,
22
22
  setShellHosts,
23
23
  shellHost
24
- } from "./chunk-DN6YKMFJ.js";
24
+ } from "./chunk-GVJBUCYJ.js";
25
25
  import {
26
26
  getSSHHosts,
27
27
  getTabType,
28
28
  setFrontendState,
29
29
  setPluginSummaries
30
- } from "./chunk-6WLECSNB.js";
30
+ } from "./chunk-DUOTWQ4Y.js";
31
31
  import {
32
32
  init_define_import_meta_env
33
33
  } from "./chunk-YGYBM7SQ.js";
@@ -4,7 +4,7 @@ import {
4
4
  getLinkedSession,
5
5
  notifySyncChanged,
6
6
  useDesktopLinked
7
- } from "./chunk-6WLECSNB.js";
7
+ } from "./chunk-DUOTWQ4Y.js";
8
8
  import "./chunk-YGYBM7SQ.js";
9
9
  export {
10
10
  SYNC_CHANGED_EVENT,
@@ -25,7 +25,7 @@ import {
25
25
  shareHost,
26
26
  updateHostAccess,
27
27
  updateRole
28
- } from "./chunk-6WLECSNB.js";
28
+ } from "./chunk-DUOTWQ4Y.js";
29
29
  import "./chunk-YGYBM7SQ.js";
30
30
  export {
31
31
  assignRoleToUser,
@@ -7,7 +7,7 @@ import {
7
7
  PluginViewPlaceholder,
8
8
  renderTabContent,
9
9
  trackTabHandle
10
- } from "./chunk-GBBKHJRQ.js";
10
+ } from "./chunk-KAOL7264.js";
11
11
  import {
12
12
  RAIL_ITEMS,
13
13
  ServerStatusProvider,
@@ -46,6 +46,7 @@ import {
46
46
  registerDashboardCard,
47
47
  registerHostAction,
48
48
  registerHostProtocol,
49
+ registerHostSection,
49
50
  registerKeybindingAction,
50
51
  registerKeybindingDefault,
51
52
  registerRailItem,
@@ -54,6 +55,7 @@ import {
54
55
  resetActionRegistry,
55
56
  resetDashboardCards,
56
57
  resetHostContributions,
58
+ resetHostSections,
57
59
  resetKeybindingRegistry,
58
60
  resetRegisteredRailItems,
59
61
  resolveLayoutTabTarget,
@@ -61,11 +63,11 @@ import {
61
63
  setRemoteServerUrlForTesting,
62
64
  useShellController,
63
65
  useTabStageStore
64
- } from "./chunk-X65V7ZRW.js";
66
+ } from "./chunk-GTTGPAMQ.js";
65
67
  import {
66
68
  setPermissionsForTesting
67
- } from "./chunk-GRH7GSKG.js";
68
- import "./chunk-IMPLAAUM.js";
69
+ } from "./chunk-D45W5IDI.js";
70
+ import "./chunk-WAPKSDXJ.js";
69
71
  import {
70
72
  SurfaceScope,
71
73
  notifyShellReady,
@@ -73,14 +75,14 @@ import {
73
75
  setShellCallbacks,
74
76
  setShellHosts,
75
77
  setShellLayoutProvider
76
- } from "./chunk-DN6YKMFJ.js";
78
+ } from "./chunk-GVJBUCYJ.js";
77
79
  import {
78
80
  getTabType,
79
81
  listTabTypes,
80
82
  resetPluginStore,
81
83
  setFrontendState,
82
84
  setPluginSummaries
83
- } from "./chunk-6WLECSNB.js";
85
+ } from "./chunk-DUOTWQ4Y.js";
84
86
  import {
85
87
  init_define_import_meta_env
86
88
  } from "./chunk-YGYBM7SQ.js";
@@ -499,6 +501,7 @@ export {
499
501
  registerDashboardCard,
500
502
  registerHostAction,
501
503
  registerHostProtocol,
504
+ registerHostSection,
502
505
  registerKeybindingAction,
503
506
  registerKeybindingDefault,
504
507
  registerRailItem,
@@ -507,6 +510,7 @@ export {
507
510
  resetActionRegistry,
508
511
  resetDashboardCards,
509
512
  resetHostContributions,
513
+ resetHostSections,
510
514
  resetKeybindingRegistry,
511
515
  resetPluginStore,
512
516
  resetRegisteredRailItems,
@@ -18,7 +18,7 @@ export type HostGroupKey = "folder" | "tag" | "status" | "protocol" | "auth";
18
18
  export type HostDensity = "comfortable" | "compact";
19
19
  export type HostTrayTrigger = "always" | "hover" | "click" | "actionsOnly";
20
20
  /** What clicking a host does when it already has an open tab. */
21
- export type HostClickBehavior = "newTab" | "focusExisting" | "focusExistingDoubleClickNew";
21
+ export type HostClickBehavior = "newTab" | "focusExisting" | "focusExistingDoubleClickNew" | "hostPage";
22
22
  export interface HostSidebarFilterState {
23
23
  status: ("online" | "offline" | "pinned")[];
24
24
  /** SSH auth type ids; plugins add their own. */
@@ -42,11 +42,13 @@ export interface ApiKey {
42
42
  expiresAt: string | null;
43
43
  lastUsedAt: string | null;
44
44
  isActive: boolean;
45
+ /** Null for full access. */
46
+ scopes?: string[] | null;
45
47
  }
46
48
  export interface CreatedApiKey extends ApiKey {
47
49
  token: string;
48
50
  }
49
- export declare function createApiKey(name: string, userId: string, expiresAt?: string): Promise<CreatedApiKey>;
51
+ export declare function createApiKey(name: string, userId: string, expiresAt?: string, scopes?: string[] | null): Promise<CreatedApiKey>;
50
52
  export declare function getApiKeys(): Promise<{
51
53
  apiKeys: ApiKey[];
52
54
  }>;
@@ -25,6 +25,11 @@ import { type ConnectionOrigin, type WebSocketConnectionTarget } from "./connect
25
25
  * reporting all behave identically.
26
26
  */
27
27
  export declare function createPluginApi(pluginId: string): AxiosInstance;
28
+ /**
29
+ * An axios client rooted at core's /operations routes: the action catalog,
30
+ * runs, approvals, events, signals and cross host resources.
31
+ */
32
+ export declare function createOperationsApi(): AxiosInstance;
28
33
  /**
29
34
  * A raw fetch on this plugin's /plugin-api mount point, for a response the
30
35
  * caller reads as a stream (server-sent events). axios buffers the whole
@@ -196,3 +196,7 @@ export { useEditorDefaultKeys } from "../sidebar/host-defaults/catalog";
196
196
  export { enabledHostProtocols, type HostProtocolDef, hostProtocolFlags, type HostProtocols, listHostProtocols, protocolEnabled, protocolPort, useHostProtocols, withProtocolSettings, } from "../sidebar/host-protocols";
197
197
  export { quickConnectTargets } from "../sidebar/quick-connect-host";
198
198
  export { groupRailItems, isCoreRailView, moveRailItem, promotableIds, type RailGroup, type RailItemDef, railItemLabel, rightDockableIds, useRailItems, } from "../sidebar/rail-items";
199
+ export { hostSectionsFor, type HostSectionDef, listHostSections, useHostSections, } from "../shell/host-sections";
200
+ export { HostTabEmbed } from "../shell/HostTabEmbed";
201
+ /** Core's /operations routes, with the user's own session. */
202
+ export declare const operationsApi: import("axios").AxiosInstance;
@@ -0,0 +1,15 @@
1
+ import type { Host } from "../../types/ui-types";
2
+ import type { TabShellCallbacks } from "./tab-registry";
3
+ /**
4
+ * Draws a registered tab type inside another view, such as a host page, with
5
+ * the same props the tab stage gives it. The embed has its own instance id, so
6
+ * it never collides with the same tool opened as a normal tab.
7
+ */
8
+ export declare function HostTabEmbed({ host, type, label, data, isVisible, shell, }: {
9
+ host: Host;
10
+ type: string;
11
+ label?: string;
12
+ data?: Record<string, unknown>;
13
+ isVisible?: boolean;
14
+ shell: TabShellCallbacks;
15
+ }): import("react").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import type { ComponentType } from "react";
2
+ import type { Host } from "../../types/ui-types";
3
+ import type { TabShellCallbacks } from "./tab-registry";
4
+ export interface HostSectionRenderProps {
5
+ host: Host;
6
+ isVisible: boolean;
7
+ shell: TabShellCallbacks;
8
+ }
9
+ /**
10
+ * A card a plugin adds to a host page. The page itself belongs to a plugin;
11
+ * core only keeps the list so any plugin can fill it.
12
+ */
13
+ export interface HostSectionDef {
14
+ id: string;
15
+ pluginId?: string;
16
+ titleKey: string;
17
+ order?: number;
18
+ when: (host: Host) => boolean;
19
+ component: ComponentType<HostSectionRenderProps>;
20
+ }
21
+ export declare const registerHostSection: (item: HostSectionDef) => () => void;
22
+ export declare const useHostSections: () => HostSectionDef[];
23
+ export declare const listHostSections: () => HostSectionDef[];
24
+ export declare const resetHostSections: () => void;
25
+ export declare function hostSectionsFor(all: HostSectionDef[], host: Host): HostSectionDef[];
package/dist/host/ui.js CHANGED
@@ -16,15 +16,16 @@ import {
16
16
  markTabSurfaceUsed,
17
17
  preloadTabSurface,
18
18
  recordHostActionPreference,
19
+ renderTabContent,
19
20
  runAdaptiveBackgroundTask,
20
21
  tabIcon,
21
22
  useInstalledPlugins,
22
23
  usePluginHostSections,
23
24
  useTabHandlesVersion
24
- } from "./chunk-GBBKHJRQ.js";
25
+ } from "./chunk-KAOL7264.js";
25
26
  import {
26
27
  Toaster
27
- } from "./chunk-BP42N374.js";
28
+ } from "./chunk-QGWRLGQB.js";
28
29
  import {
29
30
  ACCENT_PRESET_COLORS,
30
31
  BUILTIN_THEMES,
@@ -48,6 +49,7 @@ import {
48
49
  canJoinSplit,
49
50
  challengeSecondFactor,
50
51
  changeAppLanguage,
52
+ createOperationsApi,
51
53
  createPluginApp,
52
54
  createQuickConnectHost,
53
55
  defaultConnectAction,
@@ -75,6 +77,7 @@ import {
75
77
  hostEditorToolbarItemsFor,
76
78
  hostMenuItemsFor,
77
79
  hostProtocolFlags,
80
+ hostSectionsFor,
78
81
  hostStatusIndicatorsFor,
79
82
  i18n_default,
80
83
  installPluginHostBridge,
@@ -86,6 +89,7 @@ import {
86
89
  layoutLabel,
87
90
  listHostActions,
88
91
  listHostProtocols,
92
+ listHostSections,
89
93
  listPanes,
90
94
  listRegisteredRailItems,
91
95
  loadPaletteGroup,
@@ -139,6 +143,7 @@ import {
139
143
  useHostEditorSections,
140
144
  useHostEditorToolbarItems,
141
145
  useHostProtocols,
146
+ useHostSections,
142
147
  useHostStatus,
143
148
  useHostStatusIndicators,
144
149
  useIsMobile,
@@ -165,10 +170,10 @@ import {
165
170
  useThemes,
166
171
  verifySecondFactor,
167
172
  withProtocolSettings
168
- } from "./chunk-X65V7ZRW.js";
173
+ } from "./chunk-GTTGPAMQ.js";
169
174
  import {
170
175
  usePermissions
171
- } from "./chunk-GRH7GSKG.js";
176
+ } from "./chunk-D45W5IDI.js";
172
177
  import {
173
178
  AddButton,
174
179
  Card,
@@ -189,7 +194,7 @@ import {
189
194
  isPrerelease,
190
195
  reportBetaFeedbackUrl,
191
196
  reportCoreIssueUrl
192
- } from "./chunk-C52NRTA6.js";
197
+ } from "./chunk-ENDXPKBA.js";
193
198
  import {
194
199
  Button,
195
200
  DefaultsOnly,
@@ -206,7 +211,7 @@ import {
206
211
  hasVisibleFields,
207
212
  isFieldShown,
208
213
  useIsDefaultsEditor
209
- } from "./chunk-IMPLAAUM.js";
214
+ } from "./chunk-WAPKSDXJ.js";
210
215
  import {
211
216
  Action,
212
217
  Activity,
@@ -381,7 +386,7 @@ import {
381
386
  useSurfaceKind,
382
387
  useUiPreference,
383
388
  useUiPreferencesContext
384
- } from "./chunk-DN6YKMFJ.js";
389
+ } from "./chunk-GVJBUCYJ.js";
385
390
  import {
386
391
  CREDENTIAL_ROW_FIELD_KEYS,
387
392
  PRESETS,
@@ -544,7 +549,7 @@ import {
544
549
  useTabs,
545
550
  useTabsSafe,
546
551
  verifyPasswordResetCode
547
- } from "./chunk-6WLECSNB.js";
552
+ } from "./chunk-DUOTWQ4Y.js";
548
553
  import {
549
554
  define_import_meta_env_default,
550
555
  init_define_import_meta_env
@@ -33305,6 +33310,38 @@ function AuthEnrollmentSections({
33305
33310
  );
33306
33311
  }) });
33307
33312
  }
33313
+
33314
+ // src/ui/shell/HostTabEmbed.tsx
33315
+ init_define_import_meta_env();
33316
+ import { useMemo as useMemo10 } from "react";
33317
+ import { jsx as jsx55 } from "react/jsx-runtime";
33318
+ function HostTabEmbed({
33319
+ host,
33320
+ type,
33321
+ label,
33322
+ data,
33323
+ isVisible = true,
33324
+ shell: shell2
33325
+ }) {
33326
+ const tab = useMemo10(
33327
+ () => ({
33328
+ id: `embed-${type}-${host.id}`,
33329
+ instanceId: `embed-${type}-${host.id}`,
33330
+ type,
33331
+ label: label ?? host.name ?? host.ip,
33332
+ host,
33333
+ openedAt: Date.now(),
33334
+ data
33335
+ }),
33336
+ // A new host or tool is a new tab; label and data changes keep it.
33337
+ // eslint-disable-next-line react-hooks/exhaustive-deps
33338
+ [type, host.id]
33339
+ );
33340
+ return /* @__PURE__ */ jsx55("div", { className: "h-full min-h-0 flex flex-col", children: renderTabContent(tab, { shell: shell2, isVisible, isFocusedPane: isVisible }) });
33341
+ }
33342
+
33343
+ // src/ui/plugin-host/sdk-ui.ts
33344
+ var operationsApi = createOperationsApi();
33308
33345
  export {
33309
33346
  ACCENT_PRESET_COLORS,
33310
33347
  APP_VERSION,
@@ -33404,6 +33441,7 @@ export {
33404
33441
  HostFeatureFields,
33405
33442
  HostKeyVerificationDialog,
33406
33443
  HostOnly,
33444
+ HostTabEmbed,
33407
33445
  IconPicker,
33408
33446
  InlineView,
33409
33447
  Input,
@@ -33638,6 +33676,7 @@ export {
33638
33676
  hostEditorToolbarItemsFor,
33639
33677
  hostMenuItemsFor,
33640
33678
  hostProtocolFlags,
33679
+ hostSectionsFor,
33641
33680
  hostStatusIndicatorsFor,
33642
33681
  hydrateLocalSharedHostAuth,
33643
33682
  invalidateHostsAndStatusCaches,
@@ -33656,6 +33695,7 @@ export {
33656
33695
  remoteServerUrl as linkedServerUrl,
33657
33696
  listHostActions,
33658
33697
  listHostProtocols,
33698
+ listHostSections,
33659
33699
  loadPaletteGroup,
33660
33700
  logoutUser,
33661
33701
  makeHostSshSubTabs,
@@ -33669,6 +33709,7 @@ export {
33669
33709
  normalizeLanguageCode,
33670
33710
  notifySyncChanged,
33671
33711
  openInSplit,
33712
+ operationsApi,
33672
33713
  paletteEntriesFor,
33673
33714
  parseCustomKeybindings,
33674
33715
  parseServerTime,
@@ -33779,6 +33820,7 @@ export {
33779
33820
  useHostEditorSections,
33780
33821
  useHostEditorToolbarItems,
33781
33822
  useHostProtocols,
33823
+ useHostSections,
33782
33824
  useHostStatus,
33783
33825
  useHostStatusIndicators,
33784
33826
  useInstalledPlugins,
@@ -7,7 +7,7 @@ import {
7
7
  resetPermissionsCache,
8
8
  setPermissionsForTesting,
9
9
  usePermissions
10
- } from "./chunk-GRH7GSKG.js";
10
+ } from "./chunk-D45W5IDI.js";
11
11
  import "./chunk-YGYBM7SQ.js";
12
12
  export {
13
13
  hasPermission,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@termix-ssh/plugin-sdk",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "The contract between Termix core and a plugin: types, the capability catalog and the manifest schema.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {