@termix-ssh/plugin-sdk 1.0.12 → 1.0.15

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 (46) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/PLUGIN-GUIDE.md +106 -59
  3. package/dist/backend.d.ts +534 -1
  4. package/dist/backend.js +7 -0
  5. package/dist/capabilities.js +7 -0
  6. package/dist/db.js +1 -0
  7. package/dist/desktop.d.ts +0 -243
  8. package/dist/frontend.d.ts +23 -2
  9. package/dist/host/{PluginsTab-EV4MSGY6.js → PluginsTab-S33WIIGC.js} +511 -178
  10. package/dist/host/{chunk-AWR6FYDO.js → chunk-2IV3VX7F.js} +5552 -5550
  11. package/dist/host/{chunk-RUPLD6RF.js → chunk-3L45NNT5.js} +29 -84
  12. package/dist/host/{chunk-VEWOYAMZ.js → chunk-57DJU2ZA.js} +1 -1
  13. package/dist/host/{chunk-XKA3DBB2.js → chunk-V44FCJBQ.js} +135 -54
  14. package/dist/host/{chunk-X4QZKO5G.js → chunk-VFTB2RDP.js} +54 -5
  15. package/dist/host/core-classes.json +1 -1
  16. package/dist/host/{linked-server-B4NEG4MA.js → linked-server-SCJH7DSL.js} +1 -1
  17. package/dist/host/{rbac-api-OUO3LUOC.js → rbac-api-KA5IPQQL.js} +1 -1
  18. package/dist/host/testing-host.js +4 -4
  19. package/dist/host/types/src/types/index.d.ts +10 -0
  20. package/dist/host/types/src/types/onboarding.d.ts +0 -2
  21. package/dist/host/types/src/types/ui-types.d.ts +3 -1
  22. package/dist/host/types/src/ui/api/audit-log-api.d.ts +0 -10
  23. package/dist/host/types/src/ui/api/auth-methods-api.d.ts +2 -0
  24. package/dist/host/types/src/ui/api/credentials-api.d.ts +0 -22
  25. package/dist/host/types/src/ui/api/plugins-api.d.ts +4 -0
  26. package/dist/host/types/src/ui/api/settings-api.d.ts +6 -6
  27. package/dist/host/types/src/ui/api/ssh-host-management-api.d.ts +6 -28
  28. package/dist/host/types/src/ui/main-axios.d.ts +3 -3
  29. package/dist/host/types/src/ui/onboarding/onboarding-registry.d.ts +3 -1
  30. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +6 -7
  31. package/dist/host/types/src/ui/plugins/plugin-model.d.ts +20 -0
  32. package/dist/host/types/src/ui/plugins/use-plugins-manager.d.ts +3 -0
  33. package/dist/host/types/src/ui/sidebar/AuthEnrollmentSections.d.ts +4 -1
  34. package/dist/host/types/src/ui/sidebar/host-contributions.d.ts +10 -0
  35. package/dist/host/ui.js +36 -210
  36. package/dist/host/{use-permissions-6VSHHUMB.js → use-permissions-LLN6TLAL.js} +1 -1
  37. package/dist/manifest.d.ts +10 -1
  38. package/dist/manifest.js +16 -1
  39. package/dist/ssh-keys.d.ts +29 -0
  40. package/dist/ssh-keys.js +85 -0
  41. package/dist/testing.d.ts +52 -15
  42. package/dist/testing.js +279 -2
  43. package/dist/vitest-preset.js +23 -0
  44. package/package.json +5 -1
  45. package/schema/manifest.schema.json +12 -0
  46. package/dist/host/types/src/ui/sidebar/host-export-payload.d.ts +0 -30
@@ -4920,31 +4920,6 @@ async function updateSSHHost(hostId, hostData) {
4920
4920
  throw handleApiError(error, "update SSH host");
4921
4921
  }
4922
4922
  }
4923
- async function bulkImportSSHHosts(hosts, overwrite = false, credentials) {
4924
- try {
4925
- const response = await sshHostApi.post("/bulk-import", {
4926
- hosts,
4927
- overwrite,
4928
- ...credentials ? { credentials } : {}
4929
- });
4930
- invalidateHostsAndStatusCaches();
4931
- return response.data;
4932
- } catch (error) {
4933
- handleApiError(error, "bulk import SSH hosts");
4934
- }
4935
- }
4936
- async function importSSHConfigHosts(content, overwrite = false) {
4937
- try {
4938
- const response = await sshHostApi.post("/ssh-config-import", {
4939
- content,
4940
- overwrite
4941
- });
4942
- invalidateHostsAndStatusCaches();
4943
- return response.data;
4944
- } catch (error) {
4945
- handleApiError(error, "import SSH config hosts");
4946
- }
4947
- }
4948
4923
  async function bulkUpdateSSHHosts(hostIds, updates) {
4949
4924
  try {
4950
4925
  const response = await sshHostApi.patch("/bulk-update", {
@@ -4957,6 +4932,14 @@ async function bulkUpdateSSHHosts(hostIds, updates) {
4957
4932
  handleApiError(error, "bulk update SSH hosts");
4958
4933
  }
4959
4934
  }
4935
+ async function getHostPolicy() {
4936
+ try {
4937
+ const response = await sshHostApi.get("/policy");
4938
+ return response.data;
4939
+ } catch (error) {
4940
+ handleApiError(error, "load host policy");
4941
+ }
4942
+ }
4960
4943
  async function reorderSSHHosts(positions) {
4961
4944
  try {
4962
4945
  const response = await sshHostApi.put("/reorder", { positions });
@@ -4975,16 +4958,6 @@ async function deleteSSHHost(hostId) {
4975
4958
  handleApiError(error, "delete SSH host");
4976
4959
  }
4977
4960
  }
4978
- async function exportAllSSHHosts(options) {
4979
- try {
4980
- const response = await sshHostApi.get(
4981
- options?.share ? "/db/hosts/export?share=1" : "/db/hosts/export"
4982
- );
4983
- return response.data;
4984
- } catch (error) {
4985
- handleApiError(error, "export all SSH hosts");
4986
- }
4987
- }
4988
4961
 
4989
4962
  // src/ui/api/host-status-api.ts
4990
4963
  init_define_import_meta_env();
@@ -5623,20 +5596,30 @@ async function updateSessionTimeout(timeoutHours) {
5623
5596
  handleApiError(error, "update session timeout");
5624
5597
  }
5625
5598
  }
5626
- async function getBranding() {
5599
+ async function getHttpsSettings() {
5627
5600
  try {
5628
- const response = await authApi.get("/users/branding");
5601
+ const response = await authApi.get("/users/https-settings");
5629
5602
  return response.data;
5630
5603
  } catch (error) {
5631
- handleApiError(error, "fetch branding settings");
5604
+ handleApiError(error, "fetch HTTPS settings");
5632
5605
  }
5633
5606
  }
5634
- async function updateBranding(update) {
5607
+ async function updateHttpsSettings(forceHttps) {
5635
5608
  try {
5636
- const response = await authApi.patch("/users/branding", update);
5609
+ const response = await authApi.patch("/users/https-settings", {
5610
+ forceHttps
5611
+ });
5612
+ return response.data;
5613
+ } catch (error) {
5614
+ handleApiError(error, "update HTTPS settings");
5615
+ }
5616
+ }
5617
+ async function getBranding() {
5618
+ try {
5619
+ const response = await authApi.get("/users/branding");
5637
5620
  return response.data;
5638
5621
  } catch (error) {
5639
- handleApiError(error, "update branding settings");
5622
+ handleApiError(error, "fetch branding settings");
5640
5623
  }
5641
5624
  }
5642
5625
 
@@ -6221,40 +6204,6 @@ async function reorderCredentials(positions) {
6221
6204
  throw error;
6222
6205
  }
6223
6206
  }
6224
- async function generatePublicKeyFromPrivate(privateKey, keyPassword) {
6225
- try {
6226
- const response = await authApi.post("/credentials/generate-public-key", {
6227
- privateKey,
6228
- keyPassword
6229
- });
6230
- return response.data;
6231
- } catch (error) {
6232
- throw handleApiError(error, "generate public key from private key");
6233
- }
6234
- }
6235
- async function generateKeyPair(keyType, keySize, passphrase) {
6236
- try {
6237
- const response = await authApi.post("/credentials/generate-key-pair", {
6238
- keyType,
6239
- keySize,
6240
- passphrase
6241
- });
6242
- return response.data;
6243
- } catch (error) {
6244
- throw handleApiError(error, "generate SSH key pair");
6245
- }
6246
- }
6247
- async function deployCredentialToHost(credentialId, targetHostId) {
6248
- try {
6249
- const response = await authApi.post(
6250
- `/credentials/${credentialId}/deploy-to-host`,
6251
- { targetHostId }
6252
- );
6253
- return response.data;
6254
- } catch (error) {
6255
- throw handleApiError(error, "deploy credential to host");
6256
- }
6257
- }
6258
6207
 
6259
6208
  // src/ui/api/dashboard-api.ts
6260
6209
  init_define_import_meta_env();
@@ -6367,7 +6316,7 @@ async function updateRole(roleId, roleData) {
6367
6316
  try {
6368
6317
  const response = await rbacApi.put(`/rbac/roles/${roleId}`, roleData);
6369
6318
  if (roleData.permissions) {
6370
- const { notifyPermissionsChanged } = await import("./use-permissions-6VSHHUMB.js");
6319
+ const { notifyPermissionsChanged } = await import("./use-permissions-LLN6TLAL.js");
6371
6320
  notifyPermissionsChanged();
6372
6321
  }
6373
6322
  return response.data;
@@ -6949,7 +6898,7 @@ function createRemoteOriginApiInstance(path) {
6949
6898
  });
6950
6899
  instance.interceptors.request.use(
6951
6900
  async (config) => {
6952
- const { getLinkedSession: getLinkedSession2 } = await import("./linked-server-B4NEG4MA.js");
6901
+ const { getLinkedSession: getLinkedSession2 } = await import("./linked-server-SCJH7DSL.js");
6953
6902
  const linked = await getLinkedSession2();
6954
6903
  config.baseURL = linked ? `${linked.serverUrl}${path}` : "http://no-server-configured";
6955
6904
  if (config.headers.set) {
@@ -7376,12 +7325,10 @@ export {
7376
7325
  getSSHHosts,
7377
7326
  createSSHHost,
7378
7327
  updateSSHHost,
7379
- bulkImportSSHHosts,
7380
- importSSHConfigHosts,
7381
7328
  bulkUpdateSSHHosts,
7329
+ getHostPolicy,
7382
7330
  reorderSSHHosts,
7383
7331
  deleteSSHHost,
7384
- exportAllSSHHosts,
7385
7332
  websocketAuthProtocols,
7386
7333
  getLinkedSession,
7387
7334
  notifySyncChanged,
@@ -7408,8 +7355,9 @@ export {
7408
7355
  updateLogLevel,
7409
7356
  getSessionTimeout,
7410
7357
  updateSessionTimeout,
7358
+ getHttpsSettings,
7359
+ updateHttpsSettings,
7411
7360
  getBranding,
7412
- updateBranding,
7413
7361
  hydrateLocalSharedHostAuth,
7414
7362
  getConnectedRemoteApi,
7415
7363
  resolveRemoteHostId,
@@ -7463,9 +7411,6 @@ export {
7463
7411
  deleteAllHostsInFolder,
7464
7412
  renameCredentialFolder,
7465
7413
  reorderCredentials,
7466
- generatePublicKeyFromPrivate,
7467
- generateKeyPair,
7468
- deployCredentialToHost,
7469
7414
  getUptime,
7470
7415
  getRecentActivity,
7471
7416
  logActivity,
@@ -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-OUO3LUOC.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
29
+ inFlight = import("./rbac-api-KA5IPQQL.js").then(({ getMyPermissions }) => getMyPermissions()).then((result) => {
30
30
  cache = {
31
31
  permissions: result.permissions ?? [],
32
32
  isAdmin: !!result.isAdmin
@@ -3,7 +3,7 @@ import {
3
3
  hasPermission,
4
4
  resetPermissionsCache,
5
5
  usePermissions
6
- } from "./chunk-VEWOYAMZ.js";
6
+ } from "./chunk-57DJU2ZA.js";
7
7
  import {
8
8
  Button,
9
9
  Check,
@@ -80,7 +80,7 @@ import {
80
80
  withIconBoundary,
81
81
  withPluginContext,
82
82
  withPluginScope
83
- } from "./chunk-AWR6FYDO.js";
83
+ } from "./chunk-2IV3VX7F.js";
84
84
  import {
85
85
  SYNC_CHANGED_EVENT,
86
86
  TRUST_TOKEN_KEY,
@@ -130,7 +130,7 @@ import {
130
130
  usePluginStore,
131
131
  useTabTypes,
132
132
  websocketAuthProtocols
133
- } from "./chunk-RUPLD6RF.js";
133
+ } from "./chunk-3L45NNT5.js";
134
134
  import {
135
135
  define_import_meta_env_default,
136
136
  init_define_import_meta_env
@@ -268,6 +268,14 @@ async function getLoginMethods() {
268
268
  return [];
269
269
  }
270
270
  }
271
+ async function getRememberDeviceAllowed() {
272
+ try {
273
+ const response = await authApi.get("/users/auth/methods");
274
+ return response.data?.rememberDevice !== false;
275
+ } catch {
276
+ return true;
277
+ }
278
+ }
271
279
  async function submitLoginMethod(methodId, body, instanceId) {
272
280
  try {
273
281
  const response = await authApi.post(
@@ -1112,11 +1120,6 @@ var en_default = {
1112
1120
  pluginsSomeFailed: "Some plugins could not be changed. You can fix them later from the Plugins tab. Press Next to continue.",
1113
1121
  pluginsApplyFailed: "Your choices could not be saved. Try again, or continue and change them later from the Plugins tab.",
1114
1122
  pluginsLoadFailed: "The plugin list could not be loaded. You can choose plugins later from the Plugins tab.",
1115
- presetTitle: "How much do you want on screen?",
1116
- presetIntro: "Choose how much shows on screen.",
1117
- presetChangeLater: "You can switch presets or change any single setting later in Settings, under Interface.",
1118
- appearanceTitle: "Make it yours",
1119
- appearanceIntro: "Pick a theme, an accent color, a font and your language. Changes show right away, and you can change them later in Settings.",
1120
1123
  securityTitle: "Secure your account",
1121
1124
  securityIntro: "Add a passkey or an authenticator app to your account. You can also do this later in Settings, under Security.",
1122
1125
  desktopTitle: "How do you want to use Termix?",
@@ -1178,10 +1181,7 @@ var en_default = {
1178
1181
  retry: "Retry",
1179
1182
  refresh: "Refresh",
1180
1183
  optional: "Optional",
1181
- downloadSample: "Download Sample",
1182
1184
  failedToDeleteHost: "Failed to delete {{name}}",
1183
- importSkipExisting: "Import (skip existing)",
1184
- importSSHConfig: "Import from SSH config",
1185
1185
  connectionDetails: "Connection Details",
1186
1186
  ssh: "SSH",
1187
1187
  telnet: "Telnet",
@@ -1400,10 +1400,7 @@ var en_default = {
1400
1400
  noFolder: "(No folder)",
1401
1401
  deleteSelected: "Delete",
1402
1402
  exitSelection: "Exit selection",
1403
- importSkip: "Import (skip existing)",
1404
- importOverwrite: "Import (overwrite)",
1405
1403
  collapseBtn: "Collapse",
1406
- importExportBtn: "Import / Export",
1407
1404
  hostStatusesRefreshed: "Host statuses refreshed",
1408
1405
  failedToRefreshHosts: "Failed to refresh hosts",
1409
1406
  movedHostTo: 'Moved {{host}} to "{{folder}}"',
@@ -1458,6 +1455,9 @@ var en_default = {
1458
1455
  deleteFolderConfirm_one: 'Delete "{{name}}" and its {{count}} host? This cannot be undone.',
1459
1456
  deleteFolderConfirm_other: 'Delete "{{name}}" and its {{count}} hosts? This cannot be undone.',
1460
1457
  failedToMoveHosts: "Failed to move hosts",
1458
+ managedBanner: "This host is managed by {{plugin}}. Change it there. You can still pin and reorder it.",
1459
+ managedTooltip: "Managed by {{plugin}}",
1460
+ addBlocked: "Hosts are managed by {{plugin}}, so new hosts can't be added here.",
1461
1461
  failedToReorder: "Failed to reorder",
1462
1462
  expandAll: "Expand all folders",
1463
1463
  collapseAll: "Collapse all folders",
@@ -1568,35 +1568,6 @@ var en_default = {
1568
1568
  addCredentialBtn2: "Add Credential",
1569
1569
  checkingHostStatuses: "Checking host statuses...",
1570
1570
  pinnedSection: "Pinned",
1571
- hostsExported: "Hosts exported successfully",
1572
- export: {
1573
- menuItem: "Export...",
1574
- title: "Export hosts",
1575
- scope: "Scope",
1576
- scopeAll: "All",
1577
- scopeSelected: "Selected",
1578
- searchHosts: "Search hosts...",
1579
- include: "Include",
1580
- groupConnection: "Connection",
1581
- groupCredentials: "Credentials",
1582
- groupNotes: "Notes",
1583
- groupTags: "Tags & pin",
1584
- groupProxy: "Proxy",
1585
- groupJumpHosts: "Jump hosts",
1586
- groupFeatureFlags: "Plugin settings",
1587
- groupAdvanced: "Advanced config",
1588
- preview: "Preview",
1589
- moreHosts_one: "... {{count}} more host",
1590
- moreHosts_other: "... {{count}} more hosts",
1591
- summary: "{{selected}} of {{total}} hosts",
1592
- credentialsIncluded: "credentials included",
1593
- credentialsExcluded: "credentials excluded",
1594
- noneSelected: "No hosts selected",
1595
- cancel: "Cancel",
1596
- confirm: "Export",
1597
- fetchFailed: "Failed to load hosts for export",
1598
- bulkButton: "Export"
1599
- },
1600
1571
  sampleDownloaded: "Sample file downloaded",
1601
1572
  failedToDeleteCredential2: "Failed to delete credential",
1602
1573
  noFolderOption: "(No folder)",
@@ -1759,11 +1730,7 @@ var en_default = {
1759
1730
  editorUpdate: "Update Host",
1760
1731
  editorAdd: "Add Host",
1761
1732
  speedSearch: "Search hosts. Arrow keys to select, Enter to connect, Esc to close",
1762
- speedSearchList: "Host list. Type or press / to search.",
1763
- importNoHosts: "No hosts found in the file",
1764
- importTooMany: "You can import up to {{max}} hosts at once",
1765
- importSummary: "Import done: {{imported}} imported, {{updated}} updated, {{failed}} failed",
1766
- importHostsFailed: "Failed to import hosts"
1733
+ speedSearchList: "Host list. Type or press / to search."
1767
1734
  },
1768
1735
  splitScreen: {
1769
1736
  title: "Split screen",
@@ -2087,6 +2054,10 @@ var en_default = {
2087
2054
  title: "Handle sign in",
2088
2055
  consequence: "It can add a login method, a second factor or an SSH sign-in type."
2089
2056
  },
2057
+ "auth:policy": {
2058
+ title: "Set sign in rules",
2059
+ consequence: "It can sign people out when idle, limit session length, turn off remember me and require a second factor."
2060
+ },
2090
2061
  "system:tls": {
2091
2062
  title: "Manage certificates",
2092
2063
  consequence: "It can replace the certificate Termix serves over HTTPS and answer domain checks from certificate authorities."
@@ -2095,6 +2066,10 @@ var en_default = {
2095
2066
  title: "Access serial and USB devices",
2096
2067
  consequence: "It can open a physical serial port on the machine running Termix."
2097
2068
  },
2069
+ "hosts:export": {
2070
+ title: "Export hosts with their secrets",
2071
+ consequence: "Can read your hosts in full, including saved passwords and keys, and hand them out. Every export is written to the audit log."
2072
+ },
2098
2073
  "hosts:write": {
2099
2074
  title: "Create and change hosts",
2100
2075
  consequence: "It can add hosts and edit the ones you already have."
@@ -2139,10 +2114,30 @@ var en_default = {
2139
2114
  title: "Read the audit log",
2140
2115
  consequence: "It can see who did what and when."
2141
2116
  },
2117
+ "network:probe": {
2118
+ title: "Check if ports answer",
2119
+ consequence: "Can open a plain connection to any address from the server, to see if it is reachable."
2120
+ },
2121
+ "hosts:status-provide": {
2122
+ title: "Provide host status",
2123
+ consequence: "Becomes the source of the online and offline dots for every host."
2124
+ },
2125
+ "hosts:activity-provide": {
2126
+ title: "Store recent activity",
2127
+ consequence: "Becomes the store for the recent activity list of every user."
2128
+ },
2129
+ "hosts:lock": {
2130
+ title: "Manage hosts as read only",
2131
+ consequence: "Hosts it manages can't be edited, deleted or reshared by anyone else."
2132
+ },
2142
2133
  "desktop:window": {
2143
2134
  title: "Open desktop windows",
2144
2135
  consequence: "Only in the Termix desktop app."
2145
2136
  },
2137
+ "desktop:local": {
2138
+ title: "Use this computer",
2139
+ consequence: "Can read and change files, run a shell and open local ports on this computer. Only in the Termix desktop app."
2140
+ },
2146
2141
  "users:impersonate": {
2147
2142
  title: "Act as other users",
2148
2143
  consequence: "Runs background work with another user's access, such as scheduled jobs. Every use is written to the audit log."
@@ -2389,7 +2384,6 @@ var en_default = {
2389
2384
  noServerAccess: "No access to your servers",
2390
2385
  searchInstalled: "Search installed",
2391
2386
  searchPlugins: "Search plugins",
2392
- allCategories: "All",
2393
2387
  nothingMatches: "Nothing matches that.",
2394
2388
  noneInstalled: "No plugins installed yet. Browse to add some.",
2395
2389
  nothingHere: "Nothing here.",
@@ -2479,7 +2473,44 @@ var en_default = {
2479
2473
  documentation: "Documentation",
2480
2474
  envVars: "Environment variables",
2481
2475
  envRequired: "Required",
2482
- envDefault: "Default: {{value}}"
2476
+ envDefault: "Default: {{value}}",
2477
+ kinds: {
2478
+ layouts: "Layouts",
2479
+ themes: "Themes",
2480
+ tabs: "Tabs",
2481
+ panels: "Sidebar panels",
2482
+ dashboardCards: "Dashboard cards",
2483
+ protocols: "Connection types",
2484
+ auth: "Sign in methods",
2485
+ actions: "Actions",
2486
+ hostCapability: "Host settings"
2487
+ },
2488
+ filters: {
2489
+ type: "Type",
2490
+ allTypes: "All types",
2491
+ category: "Category",
2492
+ allCategories: "All categories",
2493
+ results_one: "{{count}} plugin",
2494
+ results_other: "{{count}} plugins",
2495
+ remove: "Remove filter {{name}}",
2496
+ clear: "Clear filters",
2497
+ button: "Filters",
2498
+ buttonCount: "Filters ({{count}})"
2499
+ },
2500
+ pager: {
2501
+ range: "{{from}}-{{to}} of {{total}}",
2502
+ page: "Page {{page}} of {{pages}}",
2503
+ previous: "Previous page",
2504
+ next: "Next page",
2505
+ perPage: "{{count}} per page",
2506
+ perPageLabel: "Plugins per page"
2507
+ },
2508
+ showUnsupportedHint: "These are listed but no release runs on this version yet. Update Termix to install them.",
2509
+ unsupported: "Needs a newer Termix",
2510
+ unsupportedHint: "No release of this plugin runs on this version of Termix. Update Termix to install it.",
2511
+ needsTermix: "Needs Termix {{range}}",
2512
+ showUnsupported: "Show unsupported ({{count}})",
2513
+ showMore: "Show {{count}} more ({{total}} left)"
2483
2514
  }
2484
2515
  },
2485
2516
  settings: {
@@ -3104,6 +3135,8 @@ function makeHostSshSubTabs(t, protocols2, defaultsMode = false) {
3104
3135
  init_define_import_meta_env();
3105
3136
  var actions = createRegistry(byOrderThenId);
3106
3137
  var badges = createRegistry(byOrderThenId);
3138
+ var statusIndicators = createRegistry(byOrderThenId);
3139
+ var editorToolbarItems = createRegistry(byOrderThenId);
3107
3140
  var menuItems = createRegistry(byOrderThenId);
3108
3141
  var registerHostAction = actions.register;
3109
3142
  var useHostActions = actions.useList;
@@ -3113,6 +3146,10 @@ function actionOrder(action) {
3113
3146
  var listHostActions = actions.list;
3114
3147
  var registerHostBadge = badges.register;
3115
3148
  var useHostBadges = badges.useList;
3149
+ var registerHostStatusIndicator = statusIndicators.register;
3150
+ var useHostStatusIndicators = statusIndicators.useList;
3151
+ var registerHostEditorToolbarItem = editorToolbarItems.register;
3152
+ var useHostEditorToolbarItems = editorToolbarItems.useList;
3116
3153
  var registerHostContextMenuItem = menuItems.register;
3117
3154
  var useHostContextMenuItems = menuItems.useList;
3118
3155
  function safeWhen(predicate, host) {
@@ -3135,6 +3172,12 @@ function defaultConnectAction(all, host) {
3135
3172
  function hostBadgesFor(all, host) {
3136
3173
  return all.filter((badge) => safeWhen(badge.when, host));
3137
3174
  }
3175
+ function hostStatusIndicatorsFor(all, host) {
3176
+ return all.filter((item) => safeWhen(item.when, host));
3177
+ }
3178
+ function hostEditorToolbarItemsFor(all, host) {
3179
+ return all.filter((item) => safeWhen(item.when, host));
3180
+ }
3138
3181
  function hostMenuItemsFor(all, host) {
3139
3182
  return all.filter((item) => safeWhen(item.when, host));
3140
3183
  }
@@ -3145,6 +3188,8 @@ function runHostAction(action, host, shell2) {
3145
3188
  function resetHostContributions() {
3146
3189
  actions.reset();
3147
3190
  badges.reset();
3191
+ statusIndicators.reset();
3192
+ editorToolbarItems.reset();
3148
3193
  menuItems.reset();
3149
3194
  }
3150
3195
 
@@ -3607,12 +3652,18 @@ function PluginComponent({
3607
3652
  // src/ui/onboarding/onboarding-registry.ts
3608
3653
  init_define_import_meta_env();
3609
3654
  var SECTION_POSITION = {
3655
+ start: 25,
3610
3656
  setup: 50,
3611
3657
  explore: 80,
3612
3658
  security: 95
3613
3659
  };
3660
+ var MIN_POSITION = 1;
3661
+ var MAX_POSITION = 99;
3614
3662
  var onboardingSteps = createRegistry();
3615
- function sectionPosition(section, order2 = 0) {
3663
+ function sectionPosition(section, order2 = 0, position) {
3664
+ if (typeof position === "number" && Number.isFinite(position)) {
3665
+ return Math.max(MIN_POSITION, Math.min(MAX_POSITION, position));
3666
+ }
3616
3667
  const base = SECTION_POSITION[section ?? "explore"];
3617
3668
  return base + Math.max(-1, Math.min(1, order2 / 1e3)) * 0.4;
3618
3669
  }
@@ -4071,6 +4122,7 @@ function sshHostToHost(h) {
4071
4122
  connectionOrigin: h.connectionOrigin ?? null,
4072
4123
  localOnly: !!h.localOnly,
4073
4124
  sharedCopy: !!h.sharedCopy,
4125
+ ...h.lock ? { lock: h.lock } : {},
4074
4126
  enableSsh: h.enableSsh != null ? h.enableSsh : isSshHost,
4075
4127
  sshPort: h.sshPort ?? (h.connectionType === "ssh" || !h.connectionType ? h.port : 22),
4076
4128
  protocolAuth: h.protocolAuth ?? {},
@@ -8749,7 +8801,30 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
8749
8801
  id: badge.id,
8750
8802
  pluginId,
8751
8803
  when: hostCallback(badge.when),
8752
- component: scoped(badge.component)
8804
+ component: scoped(badge.component),
8805
+ order: badge.order
8806
+ })
8807
+ );
8808
+ },
8809
+ registerHostStatusIndicator(indicator) {
8810
+ return track(
8811
+ registerHostStatusIndicator({
8812
+ id: indicator.id,
8813
+ pluginId,
8814
+ when: hostCallback(indicator.when),
8815
+ component: scoped(indicator.component),
8816
+ order: indicator.order
8817
+ })
8818
+ );
8819
+ },
8820
+ registerHostEditorToolbarItem(item) {
8821
+ return track(
8822
+ registerHostEditorToolbarItem({
8823
+ id: item.id,
8824
+ pluginId,
8825
+ when: hostCallback(item.when),
8826
+ component: scoped(item.component),
8827
+ order: item.order
8753
8828
  })
8754
8829
  );
8755
8830
  },
@@ -8903,7 +8978,8 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
8903
8978
  Component: scoped(step.component),
8904
8979
  audience: step.audience ?? "all",
8905
8980
  permission: step.permission ? resolvePluginPermission(pluginId, step.permission) : void 0,
8906
- position: sectionPosition(step.section, step.order),
8981
+ position: sectionPosition(step.section, step.order, step.position),
8982
+ replaces: step.replaces,
8907
8983
  isRelevant: when ? (ctx) => when({
8908
8984
  isAdmin: ctx.isAdmin,
8909
8985
  isDesktop: ctx.isDesktop,
@@ -9984,7 +10060,7 @@ function hostToSSHHost(h) {
9984
10060
  // src/ui/shell/tabUtils.tsx
9985
10061
  import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
9986
10062
  var PluginsTab = lazy(
9987
- () => import("./PluginsTab-EV4MSGY6.js").then((m) => ({ default: m.PluginsTab }))
10063
+ () => import("./PluginsTab-S33WIIGC.js").then((m) => ({ default: m.PluginsTab }))
9988
10064
  );
9989
10065
  function preloadTabSurface(type) {
9990
10066
  const loader = getTabType(type)?.preload;
@@ -10169,6 +10245,7 @@ export {
10169
10245
  remScale,
10170
10246
  useIsMobile,
10171
10247
  getLoginMethods,
10248
+ getRememberDeviceAllowed,
10172
10249
  submitLoginMethod,
10173
10250
  startLoginRedirect,
10174
10251
  verifySecondFactor,
@@ -10228,10 +10305,14 @@ export {
10228
10305
  actionOrder,
10229
10306
  listHostActions,
10230
10307
  useHostBadges,
10308
+ useHostStatusIndicators,
10309
+ useHostEditorToolbarItems,
10231
10310
  useHostContextMenuItems,
10232
10311
  hostActionsFor,
10233
10312
  defaultConnectAction,
10234
10313
  hostBadgesFor,
10314
+ hostStatusIndicatorsFor,
10315
+ hostEditorToolbarItemsFor,
10235
10316
  hostMenuItemsFor,
10236
10317
  runHostAction,
10237
10318
  resetHostContributions,