@termix-ssh/plugin-sdk 1.0.23 → 1.0.24

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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.24
4
+
5
+ Plugin API 1.14.0.
6
+
7
+ ### Added
8
+
9
+ - `app.registerHostSection` adds a card to the host page
10
+ - `/ui` exports `HostTabEmbed`, which draws any tab type inside another view, the host section registry, and `operationsApi` for core's `/operations` routes
11
+
3
12
  ## 1.0.23
4
13
 
5
14
  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.24 | 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;
@@ -3060,6 +3060,23 @@ function withProtocolSettings(pluginSettings, flags, list = listHostProtocols())
3060
3060
  return next;
3061
3061
  }
3062
3062
 
3063
+ // src/ui/shell/host-sections.ts
3064
+ init_define_import_meta_env();
3065
+ var sections2 = createRegistry(byOrderThenId);
3066
+ var registerHostSection = sections2.register;
3067
+ var useHostSections = sections2.useList;
3068
+ var listHostSections = sections2.list;
3069
+ var resetHostSections = sections2.reset;
3070
+ function hostSectionsFor(all, host) {
3071
+ return all.filter((section) => {
3072
+ try {
3073
+ return section.when(host);
3074
+ } catch {
3075
+ return false;
3076
+ }
3077
+ });
3078
+ }
3079
+
3063
3080
  // src/ui/dashboard/dashboard-cards-registry.ts
3064
3081
  init_define_import_meta_env();
3065
3082
  var registry3 = createRegistry();
@@ -3244,6 +3261,22 @@ function createPluginApi(pluginId) {
3244
3261
  }
3245
3262
  });
3246
3263
  }
3264
+ function createOperationsApi() {
3265
+ return new Proxy(authApi, {
3266
+ get(target, property, receiver) {
3267
+ const value = Reflect.get(target, property, receiver);
3268
+ if (typeof value !== "function") return value;
3269
+ if (property === "get" || property === "delete" || property === "post" || property === "put" || property === "patch") {
3270
+ return (url, ...rest) => value.call(
3271
+ target,
3272
+ `/operations${url.startsWith("/") ? url : `/${url}`}`,
3273
+ ...rest
3274
+ );
3275
+ }
3276
+ return value.bind(target);
3277
+ }
3278
+ });
3279
+ }
3247
3280
  function pluginFetch(pluginId, path2, init = {}) {
3248
3281
  const base = (authApi.defaults.baseURL ?? "").replace(/\/+$/, "");
3249
3282
  const headers = new Headers(init.headers);
@@ -8688,6 +8721,20 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
8688
8721
  })
8689
8722
  );
8690
8723
  },
8724
+ registerHostSection(section) {
8725
+ return track(
8726
+ registerHostSection({
8727
+ id: section.id,
8728
+ pluginId,
8729
+ titleKey: key(section.titleKey),
8730
+ order: section.order,
8731
+ when: hostCallback(section.when ?? (() => true)),
8732
+ component: scoped(
8733
+ section.component
8734
+ )
8735
+ })
8736
+ );
8737
+ },
8691
8738
  registerHostContextMenuItem(item) {
8692
8739
  return track(
8693
8740
  registerHostContextMenuItem({
@@ -9096,6 +9143,11 @@ export {
9096
9143
  hostProtocolFlags,
9097
9144
  enabledHostProtocols,
9098
9145
  withProtocolSettings,
9146
+ registerHostSection,
9147
+ useHostSections,
9148
+ listHostSections,
9149
+ resetHostSections,
9150
+ hostSectionsFor,
9099
9151
  registerDashboardCard,
9100
9152
  getRegisteredDashboardCard,
9101
9153
  registeredDashboardCardList,
@@ -9113,6 +9165,7 @@ export {
9113
9165
  registerSlotContribution,
9114
9166
  getSlotContributions,
9115
9167
  resetActionRegistry,
9168
+ createOperationsApi,
9116
9169
  pluginWsUrl,
9117
9170
  PluginComponent,
9118
9171
  onboardingSteps,
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  useTheme
4
- } from "./chunk-X65V7ZRW.js";
4
+ } from "./chunk-5W6F6GJJ.js";
5
5
  import {
6
6
  init_define_import_meta_env
7
7
  } from "./chunk-YGYBM7SQ.js";
@@ -15,7 +15,7 @@ import {
15
15
  useCompanionState,
16
16
  useIsMobile,
17
17
  useSettingsComponents
18
- } from "./chunk-X65V7ZRW.js";
18
+ } from "./chunk-5W6F6GJJ.js";
19
19
  import {
20
20
  usePermissions
21
21
  } from "./chunk-GRH7GSKG.js";
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  Toaster
4
- } from "./chunk-BP42N374.js";
4
+ } from "./chunk-EKXGDM5P.js";
5
5
  import {
6
6
  ThemeProvider,
7
7
  createPluginApp,
@@ -12,7 +12,7 @@ import {
12
12
  setPluginThemes,
13
13
  sshHostToHost,
14
14
  useTheme
15
- } from "./chunk-X65V7ZRW.js";
15
+ } from "./chunk-5W6F6GJJ.js";
16
16
  import "./chunk-GRH7GSKG.js";
17
17
  import {
18
18
  SurfaceScope,
@@ -7,7 +7,7 @@ import {
7
7
  PluginViewPlaceholder,
8
8
  renderTabContent,
9
9
  trackTabHandle
10
- } from "./chunk-GBBKHJRQ.js";
10
+ } from "./chunk-RWFXGG4Q.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,7 +63,7 @@ import {
61
63
  setRemoteServerUrlForTesting,
62
64
  useShellController,
63
65
  useTabStageStore
64
- } from "./chunk-X65V7ZRW.js";
66
+ } from "./chunk-5W6F6GJJ.js";
65
67
  import {
66
68
  setPermissionsForTesting
67
69
  } from "./chunk-GRH7GSKG.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,
@@ -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-RWFXGG4Q.js";
25
26
  import {
26
27
  Toaster
27
- } from "./chunk-BP42N374.js";
28
+ } from "./chunk-EKXGDM5P.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,7 +170,7 @@ import {
165
170
  useThemes,
166
171
  verifySecondFactor,
167
172
  withProtocolSettings
168
- } from "./chunk-X65V7ZRW.js";
173
+ } from "./chunk-5W6F6GJJ.js";
169
174
  import {
170
175
  usePermissions
171
176
  } from "./chunk-GRH7GSKG.js";
@@ -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,
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.24",
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": {