@termix-ssh/plugin-sdk 1.0.21 → 1.0.23
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 +32 -0
- package/PLUGIN-GUIDE.md +130 -3
- package/cli/commands/build.mjs +55 -36
- package/cli/commands/validate.mjs +4 -0
- package/dist/backend.d.ts +139 -7
- package/dist/capabilities.js +3 -0
- package/dist/frontend.d.ts +7 -0
- package/dist/host/{PluginsTab-HQGSDSHS.js → PluginsTab-MNQU5OJ3.js} +22 -14
- package/dist/host/{chunk-JFQGI4OD.js → chunk-6WLECSNB.js} +71 -12
- package/dist/host/chunk-BP42N374.js +53 -0
- package/dist/host/{chunk-WWFRBU2E.js → chunk-C52NRTA6.js} +82 -51
- package/dist/host/{chunk-GTHINW3L.js → chunk-DN6YKMFJ.js} +34650 -34968
- package/dist/host/chunk-GBBKHJRQ.js +1526 -0
- package/dist/host/{chunk-FGX27MAA.js → chunk-GRH7GSKG.js} +1 -1
- package/dist/host/chunk-IMPLAAUM.js +345 -0
- package/dist/host/{chunk-A5CULDWV.js → chunk-X65V7ZRW.js} +121 -1574
- package/dist/host/core-classes.json +1 -1
- package/dist/host/frame-host.css +2 -0
- package/dist/host/frame-host.js +242 -0
- package/dist/host/{linked-server-UDSFY3N7.js → linked-server-YCAJ2NX3.js} +1 -1
- package/dist/host/{rbac-api-AAAPMF52.js → rbac-api-A64TXDL5.js} +5 -1
- package/dist/host/testing-host.js +9 -6
- package/dist/host/types/src/types/host-sidebar-preferences.d.ts +2 -0
- package/dist/host/types/src/types/index.d.ts +8 -0
- package/dist/host/types/src/ui/api/plugins-api.d.ts +2 -1
- package/dist/host/types/src/ui/api/rbac-api.d.ts +19 -1
- package/dist/host/types/src/ui/components/data-view.d.ts +1 -1
- package/dist/host/types/src/ui/lib/db-health-monitor.d.ts +5 -0
- package/dist/host/types/src/ui/main-axios.d.ts +1 -1
- package/dist/host/types/src/ui/plugin-host/loader.d.ts +6 -0
- package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +1 -1
- package/dist/host/types/src/ui/plugins/use-plugins-manager.d.ts +1 -1
- package/dist/host/types/src/ui/shell/tab-registry.d.ts +2 -0
- package/dist/host/ui.js +357 -370
- package/dist/host/{use-permissions-VAND5GEG.js → use-permissions-FLQAN6I7.js} +1 -1
- package/dist/host-commands.d.ts +7 -0
- package/dist/host-commands.js +35 -5
- package/dist/manifest.d.ts +33 -1
- package/dist/manifest.js +114 -1
- package/dist/operations.d.ts +222 -0
- package/dist/operations.js +650 -0
- package/dist/testing.d.ts +9 -1
- package/dist/testing.js +45 -0
- package/package.json +9 -1
- package/schema/manifest.schema.json +67 -0
|
@@ -3,65 +3,33 @@ import {
|
|
|
3
3
|
hasPermission,
|
|
4
4
|
resetPermissionsCache,
|
|
5
5
|
usePermissions
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GRH7GSKG.js";
|
|
7
7
|
import {
|
|
8
|
-
ArrowDownToLine,
|
|
9
|
-
ArrowLeftToLine,
|
|
10
|
-
ArrowRightToLine,
|
|
11
|
-
Button,
|
|
12
|
-
Check,
|
|
13
|
-
Checkbox,
|
|
14
|
-
CheckboxIndicator,
|
|
15
|
-
CircleSlash,
|
|
16
8
|
Columns2,
|
|
17
|
-
DefaultsOnly,
|
|
18
|
-
DocsLink,
|
|
19
|
-
Eye,
|
|
20
|
-
EyeOff,
|
|
21
|
-
FakeSwitch,
|
|
22
|
-
HostDefaultBadge,
|
|
23
|
-
Input,
|
|
24
9
|
KeyRound,
|
|
25
|
-
LayoutPanelLeft,
|
|
26
10
|
LibraryBig,
|
|
27
11
|
Maximize2,
|
|
28
12
|
OPEN_PLUGINS_EVENT,
|
|
29
13
|
OPEN_PLUGIN_SETTINGS_EVENT,
|
|
30
|
-
PLUGINS_CHANGED_EVENT,
|
|
31
14
|
PLUGIN_SETTINGS_CHANGED_EVENT,
|
|
32
|
-
PanelRight,
|
|
33
15
|
Plug,
|
|
34
|
-
PluginIcon,
|
|
35
16
|
Puzzle,
|
|
36
17
|
RotateCcw,
|
|
37
18
|
Rows2,
|
|
38
|
-
SectionCard,
|
|
39
|
-
Select,
|
|
40
|
-
SelectContent,
|
|
41
|
-
SelectItem,
|
|
42
|
-
SelectTrigger,
|
|
43
|
-
SelectValue,
|
|
44
19
|
Server,
|
|
45
|
-
SettingRow,
|
|
46
20
|
Settings,
|
|
47
21
|
Terminal,
|
|
48
22
|
X,
|
|
49
23
|
Zap,
|
|
50
|
-
cn,
|
|
51
24
|
getPluginAdminSettings,
|
|
52
25
|
getPluginHostSettings,
|
|
53
26
|
getPluginUserSettings,
|
|
54
|
-
getPlugins,
|
|
55
27
|
guardCallback,
|
|
56
|
-
hasVisibleFields,
|
|
57
|
-
isFieldShown,
|
|
58
|
-
isRedactedSecret,
|
|
59
28
|
notifyShellReady,
|
|
60
29
|
notifyTabsChanged,
|
|
61
30
|
pluginDocsPage,
|
|
62
31
|
pluginDocsUrl,
|
|
63
32
|
pluginKey,
|
|
64
|
-
pluginName,
|
|
65
33
|
scopeHostArgs,
|
|
66
34
|
scopeHostCallback,
|
|
67
35
|
scopeHostFields,
|
|
@@ -83,7 +51,7 @@ import {
|
|
|
83
51
|
withIconBoundary,
|
|
84
52
|
withPluginContext,
|
|
85
53
|
withPluginScope
|
|
86
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-DN6YKMFJ.js";
|
|
87
55
|
import {
|
|
88
56
|
SYNC_CHANGED_EVENT,
|
|
89
57
|
TRUST_TOKEN_KEY,
|
|
@@ -128,95 +96,14 @@ import {
|
|
|
128
96
|
saveUserPreferences,
|
|
129
97
|
setCookie,
|
|
130
98
|
tabTypeForActivity,
|
|
131
|
-
unregisteredViewStatus,
|
|
132
99
|
usePluginStore,
|
|
133
100
|
useTabTypes,
|
|
134
101
|
websocketAuthProtocols
|
|
135
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-6WLECSNB.js";
|
|
136
103
|
import {
|
|
137
|
-
define_import_meta_env_default,
|
|
138
104
|
init_define_import_meta_env
|
|
139
105
|
} from "./chunk-YGYBM7SQ.js";
|
|
140
106
|
|
|
141
|
-
// src/ui/components/checkbox.tsx
|
|
142
|
-
init_define_import_meta_env();
|
|
143
|
-
import { jsx } from "react/jsx-runtime";
|
|
144
|
-
function Checkbox2({
|
|
145
|
-
className,
|
|
146
|
-
...props
|
|
147
|
-
}) {
|
|
148
|
-
return /* @__PURE__ */ jsx(
|
|
149
|
-
Checkbox,
|
|
150
|
-
{
|
|
151
|
-
"data-slot": "checkbox",
|
|
152
|
-
className: cn(
|
|
153
|
-
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-none border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
154
|
-
className
|
|
155
|
-
),
|
|
156
|
-
...props,
|
|
157
|
-
children: /* @__PURE__ */ jsx(
|
|
158
|
-
CheckboxIndicator,
|
|
159
|
-
{
|
|
160
|
-
"data-slot": "checkbox-indicator",
|
|
161
|
-
className: "flex items-center justify-center text-current transition-none",
|
|
162
|
-
children: /* @__PURE__ */ jsx(Check, { className: "size-3.5" })
|
|
163
|
-
}
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// src/ui/components/password-input.tsx
|
|
170
|
-
init_define_import_meta_env();
|
|
171
|
-
import * as React from "react";
|
|
172
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
173
|
-
var PasswordInput = React.forwardRef(({ className, ...props }, ref) => {
|
|
174
|
-
const [showPassword, setShowPassword] = React.useState(false);
|
|
175
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
176
|
-
/* @__PURE__ */ jsx2(
|
|
177
|
-
Input,
|
|
178
|
-
{
|
|
179
|
-
ref,
|
|
180
|
-
type: showPassword ? "text" : "password",
|
|
181
|
-
className: cn("h-11 text-base pr-12", className),
|
|
182
|
-
...props
|
|
183
|
-
}
|
|
184
|
-
),
|
|
185
|
-
/* @__PURE__ */ jsx2(
|
|
186
|
-
"button",
|
|
187
|
-
{
|
|
188
|
-
type: "button",
|
|
189
|
-
onClick: () => setShowPassword((prev) => !prev),
|
|
190
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition",
|
|
191
|
-
"aria-label": showPassword ? "Hide password" : "Show password",
|
|
192
|
-
children: showPassword ? /* @__PURE__ */ jsx2(EyeOff, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx2(Eye, { className: "h-5 w-5" })
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
] });
|
|
196
|
-
});
|
|
197
|
-
PasswordInput.displayName = "PasswordInput";
|
|
198
|
-
|
|
199
|
-
// src/ui/components/textarea.tsx
|
|
200
|
-
init_define_import_meta_env();
|
|
201
|
-
import * as React2 from "react";
|
|
202
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
203
|
-
var Textarea = React2.forwardRef(
|
|
204
|
-
({ className, ...props }, ref) => {
|
|
205
|
-
return /* @__PURE__ */ jsx3(
|
|
206
|
-
"textarea",
|
|
207
|
-
{
|
|
208
|
-
className: cn(
|
|
209
|
-
"flex min-h-[80px] w-full rounded-none border border-input bg-transparent dark:bg-input/30 px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] duration-200 outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 disabled:pointer-events-none",
|
|
210
|
-
className
|
|
211
|
-
),
|
|
212
|
-
ref,
|
|
213
|
-
...props
|
|
214
|
-
}
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
);
|
|
218
|
-
Textarea.displayName = "Textarea";
|
|
219
|
-
|
|
220
107
|
// src/ui/lib/rem.ts
|
|
221
108
|
init_define_import_meta_env();
|
|
222
109
|
var ROOT_PX = 14;
|
|
@@ -232,13 +119,13 @@ function remScale() {
|
|
|
232
119
|
|
|
233
120
|
// src/ui/hooks/use-mobile.ts
|
|
234
121
|
init_define_import_meta_env();
|
|
235
|
-
import * as
|
|
122
|
+
import * as React from "react";
|
|
236
123
|
var MOBILE_BREAKPOINT = 768;
|
|
237
124
|
function useIsMobile() {
|
|
238
|
-
const [isMobile, setIsMobile] =
|
|
125
|
+
const [isMobile, setIsMobile] = React.useState(
|
|
239
126
|
void 0
|
|
240
127
|
);
|
|
241
|
-
|
|
128
|
+
React.useEffect(() => {
|
|
242
129
|
if (isElectron()) {
|
|
243
130
|
setIsMobile(false);
|
|
244
131
|
return;
|
|
@@ -1499,6 +1386,8 @@ var en_default = {
|
|
|
1499
1386
|
closeOnOpenDesc: "Close the sidebar after you open a host from it",
|
|
1500
1387
|
showFolderPaths: "Show folder paths",
|
|
1501
1388
|
showFolderPathsDesc: "Show the parent folder path above nested subfolder names. Subfolders stay indented either way.",
|
|
1389
|
+
stripedRows: "Alternating row colors",
|
|
1390
|
+
stripedRowsDesc: "Shade every other row in the host list",
|
|
1502
1391
|
rowDetailsTitle: "Row details",
|
|
1503
1392
|
rowDetailsDesc: "Choose what shows on each host.",
|
|
1504
1393
|
showAddress: "Address",
|
|
@@ -1684,6 +1573,8 @@ var en_default = {
|
|
|
1684
1573
|
sharedBadge: "Shared",
|
|
1685
1574
|
sharedBadgeTooltip: "Shared by {{owner}} ({{level}} access)",
|
|
1686
1575
|
viewOnlyBanner: "This host is shared with you by {{owner}} with view access. The configuration is read-only.",
|
|
1576
|
+
folderRuleRemoveFromHosts: "Also remove this access from every host in the folder and its subfolders",
|
|
1577
|
+
sharedCopyBanner: "This host is shared with you by {{owner}}. The desktop keeps a read-only copy, so change it on the server and it syncs here.",
|
|
1687
1578
|
sharedEditBanner: "This host is shared with you by {{owner}} with edit access. Changes apply to the real host; authentication references can only be changed by the owner.",
|
|
1688
1579
|
ownerOnlyControl: "Only the host owner can change this",
|
|
1689
1580
|
ownerAuthPrivate: "The host owner's SSH authentication is private. Use \u201CSet personal SSH authentication\u201D from the host menu to choose your own credential.",
|
|
@@ -2119,6 +2010,18 @@ var en_default = {
|
|
|
2119
2010
|
title: "Send alerts",
|
|
2120
2011
|
consequence: "To you or other users, and through the channels they set up."
|
|
2121
2012
|
},
|
|
2013
|
+
"operations:provide": {
|
|
2014
|
+
title: "Offer actions",
|
|
2015
|
+
consequence: "Its actions can be run from Automations, the CLI, the phone app and other places, by people allowed to use them."
|
|
2016
|
+
},
|
|
2017
|
+
"operations:invoke": {
|
|
2018
|
+
title: "Run other plugins' actions",
|
|
2019
|
+
consequence: "Acts for the signed-in user on the actions its manifest lists. Approval rules still apply."
|
|
2020
|
+
},
|
|
2021
|
+
"operations:approve": {
|
|
2022
|
+
title: "Decide what needs approval",
|
|
2023
|
+
consequence: "Can let actions run with no approval, or block them, for every user."
|
|
2024
|
+
},
|
|
2122
2025
|
"notify:hub": {
|
|
2123
2026
|
title: "Receive every alert",
|
|
2124
2027
|
consequence: "Stores and delivers the alerts all plugins send, including their contents."
|
|
@@ -2862,7 +2765,7 @@ function resetRegisteredRailItems() {
|
|
|
2862
2765
|
|
|
2863
2766
|
// src/ui/sidebar/HostManagerTabs.tsx
|
|
2864
2767
|
init_define_import_meta_env();
|
|
2865
|
-
import { jsx
|
|
2768
|
+
import { jsx } from "react/jsx-runtime";
|
|
2866
2769
|
var sections = createRegistry(byOrderThenId);
|
|
2867
2770
|
var registerHostEditorSection = sections.register;
|
|
2868
2771
|
var unregisterHostEditorSection = sections.unregister;
|
|
@@ -2886,7 +2789,7 @@ function mergeByOrder(core, group, t, protocols2, defaultsMode = false) {
|
|
|
2886
2789
|
return {
|
|
2887
2790
|
id: section.id,
|
|
2888
2791
|
label: t(section.labelKey, { defaultValue: section.label }),
|
|
2889
|
-
icon: Icon ? /* @__PURE__ */
|
|
2792
|
+
icon: Icon ? /* @__PURE__ */ jsx(Icon, { className: "size-3" }) : null,
|
|
2890
2793
|
order: section.order ?? 1e3
|
|
2891
2794
|
};
|
|
2892
2795
|
});
|
|
@@ -2898,13 +2801,13 @@ function makeHostTabs(t, protocols2, defaultsMode = false) {
|
|
|
2898
2801
|
{
|
|
2899
2802
|
id: "general",
|
|
2900
2803
|
label: t("hosts.tabGeneral"),
|
|
2901
|
-
icon: /* @__PURE__ */
|
|
2804
|
+
icon: /* @__PURE__ */ jsx(Settings, { className: "size-3" }),
|
|
2902
2805
|
order: 0
|
|
2903
2806
|
},
|
|
2904
2807
|
{
|
|
2905
2808
|
id: "ssh",
|
|
2906
2809
|
label: t("hosts.tabSsh"),
|
|
2907
|
-
icon: /* @__PURE__ */
|
|
2810
|
+
icon: /* @__PURE__ */ jsx(Terminal, { className: "size-3" }),
|
|
2908
2811
|
order: 10
|
|
2909
2812
|
}
|
|
2910
2813
|
],
|
|
@@ -2920,7 +2823,7 @@ function makeHostSshSubTabs(t, protocols2, defaultsMode = false) {
|
|
|
2920
2823
|
{
|
|
2921
2824
|
id: "ssh",
|
|
2922
2825
|
label: t("hosts.tabGeneral"),
|
|
2923
|
-
icon: /* @__PURE__ */
|
|
2826
|
+
icon: /* @__PURE__ */ jsx(Settings, { className: "size-3" }),
|
|
2924
2827
|
order: 0
|
|
2925
2828
|
}
|
|
2926
2829
|
],
|
|
@@ -3394,7 +3297,7 @@ async function pluginWsUrl(pluginId, path2, options = {}) {
|
|
|
3394
3297
|
}
|
|
3395
3298
|
const token = await fetchSocketTicket() ?? localStorage.getItem("jwt");
|
|
3396
3299
|
const protocols2 = websocketAuthProtocols(token);
|
|
3397
|
-
const devProxy =
|
|
3300
|
+
const devProxy = false;
|
|
3398
3301
|
const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
3399
3302
|
if (devProxy) {
|
|
3400
3303
|
return {
|
|
@@ -3470,7 +3373,7 @@ function sectionPosition(section, order2 = 0, position) {
|
|
|
3470
3373
|
|
|
3471
3374
|
// src/ui/hooks/use-status-color-scheme.ts
|
|
3472
3375
|
init_define_import_meta_env();
|
|
3473
|
-
import { useState as
|
|
3376
|
+
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
3474
3377
|
var PREFS_KEY = "hostSidebarPreferences";
|
|
3475
3378
|
var PREFS_EVENT = "hostSidebarPreferencesChanged";
|
|
3476
3379
|
function readStatusColorScheme() {
|
|
@@ -3484,7 +3387,7 @@ function readStatusColorScheme() {
|
|
|
3484
3387
|
}
|
|
3485
3388
|
}
|
|
3486
3389
|
function useStatusColorScheme() {
|
|
3487
|
-
const [scheme, setScheme] =
|
|
3390
|
+
const [scheme, setScheme] = useState2(
|
|
3488
3391
|
readStatusColorScheme
|
|
3489
3392
|
);
|
|
3490
3393
|
useEffect2(() => {
|
|
@@ -3524,10 +3427,6 @@ function getStatusClasses(status, scheme, variant, loading = false) {
|
|
|
3524
3427
|
return online ? "border-accent-brand/40 text-accent-brand bg-accent-brand/10" : "border-border/50 text-muted-foreground/60 bg-muted/30";
|
|
3525
3428
|
}
|
|
3526
3429
|
|
|
3527
|
-
// src/ui/components/theme-provider.tsx
|
|
3528
|
-
init_define_import_meta_env();
|
|
3529
|
-
import { createContext, useContext, useEffect as useEffect3, useState as useState4 } from "react";
|
|
3530
|
-
|
|
3531
3430
|
// src/ui/look/theme-registry.ts
|
|
3532
3431
|
init_define_import_meta_env();
|
|
3533
3432
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -3611,6 +3510,10 @@ function arePluginThemesKnown() {
|
|
|
3611
3510
|
return pluginThemesKnown;
|
|
3612
3511
|
}
|
|
3613
3512
|
|
|
3513
|
+
// src/ui/components/theme-provider.tsx
|
|
3514
|
+
init_define_import_meta_env();
|
|
3515
|
+
import { createContext, useContext, useEffect as useEffect3, useState as useState3 } from "react";
|
|
3516
|
+
|
|
3614
3517
|
// src/ui/look/theme-css.ts
|
|
3615
3518
|
init_define_import_meta_env();
|
|
3616
3519
|
var LINK_ID = "termix-theme-css";
|
|
@@ -3661,7 +3564,7 @@ function applyThemeCss(id, theme) {
|
|
|
3661
3564
|
}
|
|
3662
3565
|
|
|
3663
3566
|
// src/ui/components/theme-provider.tsx
|
|
3664
|
-
import { jsx as
|
|
3567
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
3665
3568
|
var initialState = {
|
|
3666
3569
|
theme: "dark",
|
|
3667
3570
|
setTheme: () => null,
|
|
@@ -3675,10 +3578,10 @@ function ThemeProvider({
|
|
|
3675
3578
|
storageKey = "vite-ui-theme",
|
|
3676
3579
|
...props
|
|
3677
3580
|
}) {
|
|
3678
|
-
const [theme, setTheme] =
|
|
3581
|
+
const [theme, setTheme] = useState3(
|
|
3679
3582
|
() => localStorage.getItem(storageKey) || defaultTheme
|
|
3680
3583
|
);
|
|
3681
|
-
const [previewTheme, setPreviewTheme] =
|
|
3584
|
+
const [previewTheme, setPreviewTheme] = useState3(null);
|
|
3682
3585
|
const themes = useThemes();
|
|
3683
3586
|
const shownTheme = effectiveThemeId(theme);
|
|
3684
3587
|
const activeTheme = previewTheme ?? shownTheme;
|
|
@@ -3701,7 +3604,7 @@ function ThemeProvider({
|
|
|
3701
3604
|
setPreviewTheme(preview);
|
|
3702
3605
|
}
|
|
3703
3606
|
};
|
|
3704
|
-
return /* @__PURE__ */
|
|
3607
|
+
return /* @__PURE__ */ jsx2(ThemeProviderContext.Provider, { ...props, value, children });
|
|
3705
3608
|
}
|
|
3706
3609
|
var useTheme = () => {
|
|
3707
3610
|
const context = useContext(ThemeProviderContext);
|
|
@@ -3712,7 +3615,7 @@ var useTheme = () => {
|
|
|
3712
3615
|
|
|
3713
3616
|
// src/ui/hooks/useSshAuthProviders.ts
|
|
3714
3617
|
init_define_import_meta_env();
|
|
3715
|
-
import { useEffect as useEffect4, useMemo as useMemo2, useState as
|
|
3618
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
|
|
3716
3619
|
var BUILTIN_TYPES = ["password", "key", "credential", "agent", "none"];
|
|
3717
3620
|
function builtinSummary(type) {
|
|
3718
3621
|
return {
|
|
@@ -3730,7 +3633,7 @@ function builtinSummary(type) {
|
|
|
3730
3633
|
var cache = null;
|
|
3731
3634
|
function useSshAuthProviders() {
|
|
3732
3635
|
const editors = useSshAuthEditors();
|
|
3733
|
-
const [summaries, setSummaries] =
|
|
3636
|
+
const [summaries, setSummaries] = useState4(
|
|
3734
3637
|
null
|
|
3735
3638
|
);
|
|
3736
3639
|
useEffect4(() => {
|
|
@@ -3812,14 +3715,14 @@ import {
|
|
|
3812
3715
|
useContext as useContext2,
|
|
3813
3716
|
useEffect as useEffect5,
|
|
3814
3717
|
useMemo as useMemo4,
|
|
3815
|
-
useState as
|
|
3718
|
+
useState as useState5
|
|
3816
3719
|
} from "react";
|
|
3817
3720
|
|
|
3818
3721
|
// src/ui/contexts/branding-document.ts
|
|
3819
3722
|
init_define_import_meta_env();
|
|
3820
3723
|
|
|
3821
3724
|
// src/ui/contexts/BrandingContext.tsx
|
|
3822
|
-
import { jsx as
|
|
3725
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
3823
3726
|
var DEFAULT_APP_NAME = "Termix";
|
|
3824
3727
|
var BrandingContext = createContext2({
|
|
3825
3728
|
ready: false,
|
|
@@ -5210,7 +5113,7 @@ import {
|
|
|
5210
5113
|
useLayoutEffect as useLayoutEffect2,
|
|
5211
5114
|
useMemo as useMemo5,
|
|
5212
5115
|
useRef as useRef6,
|
|
5213
|
-
useState as
|
|
5116
|
+
useState as useState11
|
|
5214
5117
|
} from "react";
|
|
5215
5118
|
|
|
5216
5119
|
// src/ui/shell/stage/tab-stage-store.ts
|
|
@@ -5218,14 +5121,14 @@ init_define_import_meta_env();
|
|
|
5218
5121
|
function createTabStageStore() {
|
|
5219
5122
|
const nodes = /* @__PURE__ */ new Map();
|
|
5220
5123
|
const paneEls = /* @__PURE__ */ new Map();
|
|
5221
|
-
const
|
|
5124
|
+
const listeners8 = /* @__PURE__ */ new Set();
|
|
5222
5125
|
let normalView = null;
|
|
5223
|
-
let
|
|
5126
|
+
let version3 = 0;
|
|
5224
5127
|
let order2 = [];
|
|
5225
5128
|
let lastAnimatedTabId = null;
|
|
5226
5129
|
const bump = () => {
|
|
5227
|
-
|
|
5228
|
-
for (const listener of
|
|
5130
|
+
version3 += 1;
|
|
5131
|
+
for (const listener of listeners8) listener();
|
|
5229
5132
|
};
|
|
5230
5133
|
function getNode(tabId, ownBackground) {
|
|
5231
5134
|
let el = nodes.get(tabId);
|
|
@@ -5327,18 +5230,18 @@ function createTabStageStore() {
|
|
|
5327
5230
|
setNormalView,
|
|
5328
5231
|
place,
|
|
5329
5232
|
subscribe: (listener) => {
|
|
5330
|
-
|
|
5233
|
+
listeners8.add(listener);
|
|
5331
5234
|
return () => {
|
|
5332
|
-
|
|
5235
|
+
listeners8.delete(listener);
|
|
5333
5236
|
};
|
|
5334
5237
|
},
|
|
5335
|
-
version: () =>
|
|
5238
|
+
version: () => version3
|
|
5336
5239
|
};
|
|
5337
5240
|
}
|
|
5338
5241
|
|
|
5339
5242
|
// src/ui/shell/controller/use-regions.ts
|
|
5340
5243
|
init_define_import_meta_env();
|
|
5341
|
-
import { useCallback as useCallback2, useEffect as useEffect6, useRef, useState as
|
|
5244
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useRef, useState as useState6 } from "react";
|
|
5342
5245
|
var MIN_WIDTH = 160;
|
|
5343
5246
|
var MAX_WIDTH = 480;
|
|
5344
5247
|
function clampWidth(width) {
|
|
@@ -5371,15 +5274,15 @@ function startDockDrag(e, startW, sign, setWidth, setDragging) {
|
|
|
5371
5274
|
}
|
|
5372
5275
|
var DOCK_DEFAULT_WIDTH = 291;
|
|
5373
5276
|
function useRegions(isMobile) {
|
|
5374
|
-
const [sidebarOpen, setSidebarOpen] =
|
|
5375
|
-
const [railView, setRailView] =
|
|
5376
|
-
const [sidebarWidth, setSidebarWidth] =
|
|
5277
|
+
const [sidebarOpen, setSidebarOpen] = useState6(true);
|
|
5278
|
+
const [railView, setRailView] = useState6("hosts");
|
|
5279
|
+
const [sidebarWidth, setSidebarWidth] = useState6(() => {
|
|
5377
5280
|
const saved = localStorage.getItem("termix_sidebarWidth");
|
|
5378
5281
|
return saved ? parseInt(saved, 10) : 291;
|
|
5379
5282
|
});
|
|
5380
|
-
const [sidebarDragging, setSidebarDragging] =
|
|
5381
|
-
const [panelEditing, setPanelEditing] =
|
|
5382
|
-
const [scopeEditing, setScopeEditing] =
|
|
5283
|
+
const [sidebarDragging, setSidebarDragging] = useState6(false);
|
|
5284
|
+
const [panelEditing, setPanelEditing] = useState6({});
|
|
5285
|
+
const [scopeEditing, setScopeEditing] = useState6({});
|
|
5383
5286
|
const editingSetters = useRef(
|
|
5384
5287
|
/* @__PURE__ */ new Map()
|
|
5385
5288
|
);
|
|
@@ -5405,15 +5308,15 @@ function useRegions(isMobile) {
|
|
|
5405
5308
|
);
|
|
5406
5309
|
return editingSetters.current.get(key);
|
|
5407
5310
|
}, []);
|
|
5408
|
-
const [rightRailView, setRightRailView] =
|
|
5311
|
+
const [rightRailView, setRightRailView] = useState6(() => {
|
|
5409
5312
|
const saved = localStorage.getItem("termix_rightRailView");
|
|
5410
5313
|
return saved && rightDockableIds().includes(saved) ? saved : null;
|
|
5411
5314
|
});
|
|
5412
|
-
const [rightSidebarWidth, setRightSidebarWidth] =
|
|
5315
|
+
const [rightSidebarWidth, setRightSidebarWidth] = useState6(() => {
|
|
5413
5316
|
const saved = localStorage.getItem("termix_rightSidebarWidth");
|
|
5414
5317
|
return saved ? parseInt(saved, 10) : 291;
|
|
5415
5318
|
});
|
|
5416
|
-
const [rightSidebarDragging, setRightSidebarDragging] =
|
|
5319
|
+
const [rightSidebarDragging, setRightSidebarDragging] = useState6(false);
|
|
5417
5320
|
const lastRightRailViewRef = useRef(
|
|
5418
5321
|
localStorage.getItem("termix_lastRightRailView")
|
|
5419
5322
|
);
|
|
@@ -5524,7 +5427,7 @@ function useRegions(isMobile) {
|
|
|
5524
5427
|
|
|
5525
5428
|
// src/ui/shell/controller/use-hosts.ts
|
|
5526
5429
|
init_define_import_meta_env();
|
|
5527
|
-
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef2, useState as
|
|
5430
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef2, useState as useState7 } from "react";
|
|
5528
5431
|
|
|
5529
5432
|
// src/ui/sidebar/build-host-tree.ts
|
|
5530
5433
|
init_define_import_meta_env();
|
|
@@ -5596,10 +5499,10 @@ function buildHostTree(hosts, folderMeta) {
|
|
|
5596
5499
|
|
|
5597
5500
|
// src/ui/shell/controller/use-hosts.ts
|
|
5598
5501
|
function useHostList() {
|
|
5599
|
-
const [tree, setTree] =
|
|
5600
|
-
const [loading, setLoading] =
|
|
5601
|
-
const [loaded, setLoaded] =
|
|
5602
|
-
const [list, setList] =
|
|
5502
|
+
const [tree, setTree] = useState7(null);
|
|
5503
|
+
const [loading, setLoading] = useState7(true);
|
|
5504
|
+
const [loaded, setLoaded] = useState7(false);
|
|
5505
|
+
const [list, setList] = useState7([]);
|
|
5603
5506
|
const listRef = useRef2(list);
|
|
5604
5507
|
listRef.current = list;
|
|
5605
5508
|
const reload = useCallback3(async () => {
|
|
@@ -5656,7 +5559,7 @@ import {
|
|
|
5656
5559
|
useCallback as useCallback4,
|
|
5657
5560
|
useEffect as useEffect8,
|
|
5658
5561
|
useRef as useRef3,
|
|
5659
|
-
useState as
|
|
5562
|
+
useState as useState8
|
|
5660
5563
|
} from "react";
|
|
5661
5564
|
import { toast } from "sonner";
|
|
5662
5565
|
import { useTranslation } from "react-i18next";
|
|
@@ -5708,10 +5611,10 @@ function useTabs({
|
|
|
5708
5611
|
}) {
|
|
5709
5612
|
const { t } = useTranslation();
|
|
5710
5613
|
const splitLabel = useSplitLabel();
|
|
5711
|
-
const [tabs, setTabs] =
|
|
5712
|
-
const [activeTabId, setActiveTabId] =
|
|
5713
|
-
const [tabsReady, setTabsReady] =
|
|
5714
|
-
const [backgroundTabRecords, setBackgroundTabRecords] =
|
|
5614
|
+
const [tabs, setTabs] = useState8([dashboardTab(t("nav.dashboard"))]);
|
|
5615
|
+
const [activeTabId, setActiveTabId] = useState8("dashboard");
|
|
5616
|
+
const [tabsReady, setTabsReady] = useState8(false);
|
|
5617
|
+
const [backgroundTabRecords, setBackgroundTabRecords] = useState8([]);
|
|
5715
5618
|
const paneLayoutRestoredRef = useRef3(false);
|
|
5716
5619
|
const splitTabsRestoredRef = useRef3(false);
|
|
5717
5620
|
const splitOpsRef = useRef3({
|
|
@@ -5800,14 +5703,14 @@ function useTabs({
|
|
|
5800
5703
|
if (!isSplitTab(active)) return activeTabId;
|
|
5801
5704
|
return findPane(active.split, active.split.focusedPaneId)?.tabId ?? "";
|
|
5802
5705
|
})();
|
|
5803
|
-
const [lastTerminalTabId, setLastTerminalTabId] =
|
|
5706
|
+
const [lastTerminalTabId, setLastTerminalTabId] = useState8(activeTabId);
|
|
5804
5707
|
useEffect8(() => {
|
|
5805
5708
|
const working = tabs.find((t2) => t2.id === workingTabId);
|
|
5806
5709
|
if (working && getTabType(working.type)?.commandTarget) {
|
|
5807
5710
|
setLastTerminalTabId(working.id);
|
|
5808
5711
|
}
|
|
5809
5712
|
}, [workingTabId, tabs]);
|
|
5810
|
-
const [showTabNumbers, setShowTabNumbers] =
|
|
5713
|
+
const [showTabNumbers, setShowTabNumbers] = useState8(
|
|
5811
5714
|
() => localStorage.getItem("showTabNumbers") === "true"
|
|
5812
5715
|
);
|
|
5813
5716
|
useEffect8(() => {
|
|
@@ -6361,7 +6264,7 @@ function useSplit({
|
|
|
6361
6264
|
tabsState,
|
|
6362
6265
|
isMobile,
|
|
6363
6266
|
paneEls,
|
|
6364
|
-
callbacks
|
|
6267
|
+
callbacks,
|
|
6365
6268
|
resizeAllTerminals
|
|
6366
6269
|
}) {
|
|
6367
6270
|
const { t } = useTranslation2();
|
|
@@ -6760,8 +6663,8 @@ function useSplit({
|
|
|
6760
6663
|
};
|
|
6761
6664
|
}
|
|
6762
6665
|
const pickerShell = {
|
|
6763
|
-
...
|
|
6764
|
-
openTab: (host, type, options) =>
|
|
6666
|
+
...callbacks,
|
|
6667
|
+
openTab: (host, type, options) => callbacks.openTab(host, type, { ...options, forceNewTab: true })
|
|
6765
6668
|
};
|
|
6766
6669
|
const split = {
|
|
6767
6670
|
active: activeSplit,
|
|
@@ -6927,7 +6830,7 @@ function useWorkspaceLayout(tabsState, regions) {
|
|
|
6927
6830
|
|
|
6928
6831
|
// src/ui/shell/controller/use-shell-keybindings.ts
|
|
6929
6832
|
init_define_import_meta_env();
|
|
6930
|
-
import { useEffect as useEffect11, useRef as useRef5, useState as
|
|
6833
|
+
import { useEffect as useEffect11, useRef as useRef5, useState as useState9 } from "react";
|
|
6931
6834
|
|
|
6932
6835
|
// src/ui/lib/pane-nav-hotkey.ts
|
|
6933
6836
|
init_define_import_meta_env();
|
|
@@ -7031,7 +6934,7 @@ function useShellKeybindings({
|
|
|
7031
6934
|
closeActiveTabRef.current();
|
|
7032
6935
|
});
|
|
7033
6936
|
}, []);
|
|
7034
|
-
const [commandPaletteShortcutEnabled, setCommandPaletteShortcutEnabled] =
|
|
6937
|
+
const [commandPaletteShortcutEnabled, setCommandPaletteShortcutEnabled] = useState9(() => {
|
|
7035
6938
|
const v = localStorage.getItem("commandPaletteShortcutEnabled");
|
|
7036
6939
|
return v !== null ? v === "true" : true;
|
|
7037
6940
|
});
|
|
@@ -7098,7 +7001,7 @@ function useShellKeybindings({
|
|
|
7098
7001
|
const tabDigit = getTabJumpDigit(e);
|
|
7099
7002
|
if (tabDigit !== null) {
|
|
7100
7003
|
const currentTabs = tabsRef.current.filter(
|
|
7101
|
-
(tab) => !tab.parentSplitTabId
|
|
7004
|
+
(tab) => !tab.parentSplitTabId && tab.type !== "dashboard"
|
|
7102
7005
|
);
|
|
7103
7006
|
const index = tabDigit - 1;
|
|
7104
7007
|
if (index < currentTabs.length) {
|
|
@@ -7144,7 +7047,7 @@ function useShellKeybindings({
|
|
|
7144
7047
|
|
|
7145
7048
|
// src/ui/shell/controller/use-shell-lifecycle.ts
|
|
7146
7049
|
init_define_import_meta_env();
|
|
7147
|
-
import { useCallback as useCallback5, useEffect as useEffect12, useState as
|
|
7050
|
+
import { useCallback as useCallback5, useEffect as useEffect12, useState as useState10 } from "react";
|
|
7148
7051
|
import { toast as toast3 } from "sonner";
|
|
7149
7052
|
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
7150
7053
|
var SNAPSHOT_KEYS = [
|
|
@@ -7223,12 +7126,12 @@ function useShellLifecycle({
|
|
|
7223
7126
|
}) {
|
|
7224
7127
|
const { t, i18n: i18n2 } = useTranslation3();
|
|
7225
7128
|
const { setTheme } = useTheme();
|
|
7226
|
-
const [userPrefs, setUserPrefs] =
|
|
7129
|
+
const [userPrefs, setUserPrefs] = useState10({
|
|
7227
7130
|
reopenTabsOnLogin: false
|
|
7228
7131
|
});
|
|
7229
|
-
const [userPrefsLoaded, setUserPrefsLoaded] =
|
|
7230
|
-
const [isAdmin, setIsAdmin] =
|
|
7231
|
-
const [isAppFullscreen, setIsAppFullscreen] =
|
|
7132
|
+
const [userPrefsLoaded, setUserPrefsLoaded] = useState10(false);
|
|
7133
|
+
const [isAdmin, setIsAdmin] = useState10(false);
|
|
7134
|
+
const [isAppFullscreen, setIsAppFullscreen] = useState10(
|
|
7232
7135
|
() => !!document.fullscreenElement
|
|
7233
7136
|
);
|
|
7234
7137
|
useEffect12(() => {
|
|
@@ -7359,7 +7262,7 @@ function useShellSnapshot() {
|
|
|
7359
7262
|
}
|
|
7360
7263
|
|
|
7361
7264
|
// src/ui/shell/controller/ShellControllerProvider.tsx
|
|
7362
|
-
import { jsx as
|
|
7265
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
7363
7266
|
var ShellControllerContext = createContext3(null);
|
|
7364
7267
|
var TabStageContext = createContext3(null);
|
|
7365
7268
|
function useShellController() {
|
|
@@ -7391,7 +7294,7 @@ function ShellControllerProvider({
|
|
|
7391
7294
|
useTabTypes();
|
|
7392
7295
|
const { settled: pluginsSettled } = usePluginStore();
|
|
7393
7296
|
const isMobile = useIsMobile();
|
|
7394
|
-
const [stageStore] =
|
|
7297
|
+
const [stageStore] = useState11(createTabStageStore);
|
|
7395
7298
|
const confirmRef = useRef6(null);
|
|
7396
7299
|
const openSingletonRef = useRef6(
|
|
7397
7300
|
() => void 0
|
|
@@ -7402,7 +7305,7 @@ function ShellControllerProvider({
|
|
|
7402
7305
|
});
|
|
7403
7306
|
const regions = useRegions(isMobile);
|
|
7404
7307
|
const hosts = useHostList();
|
|
7405
|
-
const [paletteOpen, setPaletteOpen] =
|
|
7308
|
+
const [paletteOpen, setPaletteOpen] = useState11(false);
|
|
7406
7309
|
const tabsState = useTabs({
|
|
7407
7310
|
hosts: hosts.list,
|
|
7408
7311
|
hostsRef: hosts.listRef,
|
|
@@ -7459,6 +7362,10 @@ function ShellControllerProvider({
|
|
|
7459
7362
|
regions.right.setView((prev) => prev === id ? null : prev);
|
|
7460
7363
|
},
|
|
7461
7364
|
openHostEditor: (draft) => requestManage({ kind: "host", hostId: null, draft }),
|
|
7365
|
+
editHost: (hostId) => {
|
|
7366
|
+
requestManage({ kind: "host", hostId: String(hostId) });
|
|
7367
|
+
if (isMobile) regions.left.setOpen(false);
|
|
7368
|
+
},
|
|
7462
7369
|
saveQuickConnect: tabsState.saveQuickConnectHost,
|
|
7463
7370
|
confirm: (options) => confirmRef.current ? confirmRef.current(options) : Promise.resolve(false)
|
|
7464
7371
|
};
|
|
@@ -7466,7 +7373,7 @@ function ShellControllerProvider({
|
|
|
7466
7373
|
useLayoutEffect2(() => {
|
|
7467
7374
|
shellImplRef.current = shellCallbacksImpl;
|
|
7468
7375
|
});
|
|
7469
|
-
const
|
|
7376
|
+
const callbacks = useMemo5(
|
|
7470
7377
|
() => ({
|
|
7471
7378
|
openTab: (...args) => shellImplRef.current.openTab(...args),
|
|
7472
7379
|
openSingletonTab: (...args) => shellImplRef.current.openSingletonTab(...args),
|
|
@@ -7476,6 +7383,7 @@ function ShellControllerProvider({
|
|
|
7476
7383
|
openRailView: (...args) => shellImplRef.current.openRailView(...args),
|
|
7477
7384
|
closeRailView: (...args) => shellImplRef.current.closeRailView(...args),
|
|
7478
7385
|
openHostEditor: (...args) => shellImplRef.current.openHostEditor?.(...args),
|
|
7386
|
+
editHost: (...args) => shellImplRef.current.editHost?.(...args),
|
|
7479
7387
|
saveQuickConnect: (...args) => shellImplRef.current.saveQuickConnect(...args),
|
|
7480
7388
|
confirm: (...args) => shellImplRef.current.confirm(...args)
|
|
7481
7389
|
}),
|
|
@@ -7483,13 +7391,13 @@ function ShellControllerProvider({
|
|
|
7483
7391
|
);
|
|
7484
7392
|
const panelCallbacks = useMemo5(
|
|
7485
7393
|
() => ({
|
|
7486
|
-
...
|
|
7394
|
+
...callbacks,
|
|
7487
7395
|
openTab: (...args) => {
|
|
7488
|
-
|
|
7396
|
+
callbacks.openTab(...args);
|
|
7489
7397
|
if (isMobile) regions.left.setOpen(false);
|
|
7490
7398
|
}
|
|
7491
7399
|
}),
|
|
7492
|
-
[
|
|
7400
|
+
[callbacks, isMobile]
|
|
7493
7401
|
);
|
|
7494
7402
|
const resizeAllTerminals = useCallback6(() => {
|
|
7495
7403
|
const id = requestAnimationFrame(() => {
|
|
@@ -7506,7 +7414,7 @@ function ShellControllerProvider({
|
|
|
7506
7414
|
tabsState,
|
|
7507
7415
|
isMobile,
|
|
7508
7416
|
paneEls: stageStore.paneEls,
|
|
7509
|
-
callbacks
|
|
7417
|
+
callbacks,
|
|
7510
7418
|
resizeAllTerminals
|
|
7511
7419
|
});
|
|
7512
7420
|
useEffect13(() => {
|
|
@@ -7531,7 +7439,7 @@ function ShellControllerProvider({
|
|
|
7531
7439
|
toggleFullscreen: lifecycle.toggleAppFullscreen
|
|
7532
7440
|
});
|
|
7533
7441
|
useEffect13(() => {
|
|
7534
|
-
setShellCallbacks(
|
|
7442
|
+
setShellCallbacks(callbacks);
|
|
7535
7443
|
});
|
|
7536
7444
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
7537
7445
|
const controller = {
|
|
@@ -7580,7 +7488,7 @@ function ShellControllerProvider({
|
|
|
7580
7488
|
active: lifecycle.isAppFullscreen,
|
|
7581
7489
|
toggle: lifecycle.toggleAppFullscreen
|
|
7582
7490
|
},
|
|
7583
|
-
callbacks
|
|
7491
|
+
callbacks,
|
|
7584
7492
|
panelCallbacks,
|
|
7585
7493
|
settings: {
|
|
7586
7494
|
username,
|
|
@@ -7597,7 +7505,7 @@ function ShellControllerProvider({
|
|
|
7597
7505
|
publishShellController(controller);
|
|
7598
7506
|
});
|
|
7599
7507
|
useEffect13(() => () => publishShellController(null), []);
|
|
7600
|
-
return /* @__PURE__ */
|
|
7508
|
+
return /* @__PURE__ */ jsx4(TabStageContext.Provider, { value: stageStore, children: /* @__PURE__ */ jsx4(ShellControllerContext.Provider, { value: controller, children }) });
|
|
7601
7509
|
}
|
|
7602
7510
|
|
|
7603
7511
|
// src/ui/lib/adaptive-polling.ts
|
|
@@ -7706,7 +7614,7 @@ import {
|
|
|
7706
7614
|
useRef as useRef7,
|
|
7707
7615
|
useMemo as useMemo6,
|
|
7708
7616
|
useSyncExternalStore as useSyncExternalStore8,
|
|
7709
|
-
useState as
|
|
7617
|
+
useState as useState12
|
|
7710
7618
|
} from "react";
|
|
7711
7619
|
|
|
7712
7620
|
// src/ui/lib/server-status-store.ts
|
|
@@ -7800,7 +7708,7 @@ var ServerStatusStore = class {
|
|
|
7800
7708
|
};
|
|
7801
7709
|
|
|
7802
7710
|
// src/ui/lib/ServerStatusContext.tsx
|
|
7803
|
-
import { jsx as
|
|
7711
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
7804
7712
|
var StatusStoreContext = createContext4(null);
|
|
7805
7713
|
var ServerStatusContext = createContext4(null);
|
|
7806
7714
|
var activeStore = null;
|
|
@@ -7817,7 +7725,7 @@ function ServerStatusProvider({
|
|
|
7817
7725
|
storeRef.current = new ServerStatusStore();
|
|
7818
7726
|
}
|
|
7819
7727
|
const store = storeRef.current;
|
|
7820
|
-
const [
|
|
7728
|
+
const [version3, setVersion] = useState12(0);
|
|
7821
7729
|
const mountedRef = useRef7(true);
|
|
7822
7730
|
const refreshInFlightRef = useRef7(null);
|
|
7823
7731
|
useEffect14(() => store.subscribeAll(() => setVersion((v) => v + 1)), [store]);
|
|
@@ -7900,9 +7808,9 @@ function ServerStatusProvider({
|
|
|
7900
7808
|
}),
|
|
7901
7809
|
// version refreshes the statuses/initialLoadComplete snapshots
|
|
7902
7810
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
7903
|
-
[
|
|
7811
|
+
[version3, refreshStatuses, getStatus]
|
|
7904
7812
|
);
|
|
7905
|
-
return /* @__PURE__ */
|
|
7813
|
+
return /* @__PURE__ */ jsx5(StatusStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx5(ServerStatusContext.Provider, { value: contextValue, children }) });
|
|
7906
7814
|
}
|
|
7907
7815
|
function useStatusStore() {
|
|
7908
7816
|
const store = useContext4(StatusStoreContext);
|
|
@@ -7952,7 +7860,7 @@ function useOptionalHostStatusEntry(hostId) {
|
|
|
7952
7860
|
|
|
7953
7861
|
// src/ui/plugin-host/bridge.ts
|
|
7954
7862
|
init_define_import_meta_env();
|
|
7955
|
-
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo8, useState as
|
|
7863
|
+
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo8, useState as useState13 } from "react";
|
|
7956
7864
|
|
|
7957
7865
|
// src/ui/shell/companions.ts
|
|
7958
7866
|
init_define_import_meta_env();
|
|
@@ -8272,7 +8180,7 @@ var pluginHostBridge = {
|
|
|
8272
8180
|
},
|
|
8273
8181
|
useSettings(pluginId, scope, hostId) {
|
|
8274
8182
|
const numericHostId = hostId === void 0 ? void 0 : Number.parseInt(String(hostId), 10);
|
|
8275
|
-
const [state2, setState] =
|
|
8183
|
+
const [state2, setState] = useState13({ values: {}, loaded: false });
|
|
8276
8184
|
useEffect15(() => {
|
|
8277
8185
|
let cancelled = false;
|
|
8278
8186
|
if (scope === "host" && !Number.isFinite(numericHostId)) return;
|
|
@@ -8328,7 +8236,7 @@ var pluginHostBridge = {
|
|
|
8328
8236
|
);
|
|
8329
8237
|
},
|
|
8330
8238
|
useCurrentUser() {
|
|
8331
|
-
const [user, setUser] =
|
|
8239
|
+
const [user, setUser] = useState13(null);
|
|
8332
8240
|
useEffect15(() => {
|
|
8333
8241
|
let cancelled = false;
|
|
8334
8242
|
loadCurrentUser().then((next) => {
|
|
@@ -8912,8 +8820,8 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8912
8820
|
},
|
|
8913
8821
|
registerOnboardingStep(step) {
|
|
8914
8822
|
requireStepId(step.id, "onboarding step");
|
|
8915
|
-
const
|
|
8916
|
-
if (!Number.isInteger(
|
|
8823
|
+
const version3 = step.version ?? 1;
|
|
8824
|
+
if (!Number.isInteger(version3) || version3 < 1) {
|
|
8917
8825
|
throw new Error(
|
|
8918
8826
|
`${pluginId}: onboarding step "${step.id}" needs a whole version of 1 or more`
|
|
8919
8827
|
);
|
|
@@ -8923,7 +8831,7 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8923
8831
|
onboardingSteps.register({
|
|
8924
8832
|
id: pluginStepKey(pluginId, step.id),
|
|
8925
8833
|
pluginId,
|
|
8926
|
-
version:
|
|
8834
|
+
version: version3,
|
|
8927
8835
|
titleKey: key(step.titleKey),
|
|
8928
8836
|
descriptionKey: step.descriptionKey ? key(step.descriptionKey) : void 0,
|
|
8929
8837
|
icon: step.icon ? withIconBoundary(pluginId, step.icon) : void 0,
|
|
@@ -9061,918 +8969,6 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
9061
8969
|
};
|
|
9062
8970
|
}
|
|
9063
8971
|
|
|
9064
|
-
// src/ui/hooks/use-installed-plugins.ts
|
|
9065
|
-
init_define_import_meta_env();
|
|
9066
|
-
import { useEffect as useEffect17, useState as useState15 } from "react";
|
|
9067
|
-
function useInstalledPlugins() {
|
|
9068
|
-
const [plugins, setPlugins] = useState15([]);
|
|
9069
|
-
useEffect17(() => {
|
|
9070
|
-
let cancelled = false;
|
|
9071
|
-
let request = 0;
|
|
9072
|
-
const load2 = () => {
|
|
9073
|
-
const current2 = ++request;
|
|
9074
|
-
void getPlugins().then((loaded) => {
|
|
9075
|
-
if (!cancelled && current2 === request) setPlugins(loaded);
|
|
9076
|
-
}).catch(() => {
|
|
9077
|
-
});
|
|
9078
|
-
};
|
|
9079
|
-
load2();
|
|
9080
|
-
window.addEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9081
|
-
return () => {
|
|
9082
|
-
cancelled = true;
|
|
9083
|
-
window.removeEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9084
|
-
};
|
|
9085
|
-
}, []);
|
|
9086
|
-
return plugins;
|
|
9087
|
-
}
|
|
9088
|
-
|
|
9089
|
-
// src/ui/settings/SettingsFields.tsx
|
|
9090
|
-
init_define_import_meta_env();
|
|
9091
|
-
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
9092
|
-
import { Fragment, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
9093
|
-
function SettingsFieldRow({
|
|
9094
|
-
pluginId,
|
|
9095
|
-
field,
|
|
9096
|
-
values,
|
|
9097
|
-
setValue,
|
|
9098
|
-
running,
|
|
9099
|
-
error,
|
|
9100
|
-
disabled = false,
|
|
9101
|
-
defaultKey
|
|
9102
|
-
}) {
|
|
9103
|
-
const { t } = useTranslation4();
|
|
9104
|
-
useSettingsComponents();
|
|
9105
|
-
const label = (key) => key ? t(pluginKey(pluginId, key)) : "";
|
|
9106
|
-
if (field.type === "custom") {
|
|
9107
|
-
const Component = getSettingsComponent(pluginId, field.component);
|
|
9108
|
-
if (!Component) return null;
|
|
9109
|
-
return /* @__PURE__ */ jsx9(
|
|
9110
|
-
Component,
|
|
9111
|
-
{
|
|
9112
|
-
pluginId,
|
|
9113
|
-
values,
|
|
9114
|
-
setValue,
|
|
9115
|
-
running
|
|
9116
|
-
}
|
|
9117
|
-
);
|
|
9118
|
-
}
|
|
9119
|
-
const value = values[field.key];
|
|
9120
|
-
const readOnly = disabled || !running;
|
|
9121
|
-
const description = field.descriptionKey ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
9122
|
-
label(field.descriptionKey),
|
|
9123
|
-
error && /* @__PURE__ */ jsx9("span", { className: "block text-destructive mt-0.5", children: error })
|
|
9124
|
-
] }) : error ? /* @__PURE__ */ jsx9("span", { className: "text-destructive", children: error }) : void 0;
|
|
9125
|
-
const control = /* @__PURE__ */ jsx9(
|
|
9126
|
-
FieldControl,
|
|
9127
|
-
{
|
|
9128
|
-
pluginId,
|
|
9129
|
-
field,
|
|
9130
|
-
value,
|
|
9131
|
-
setValue,
|
|
9132
|
-
readOnly
|
|
9133
|
-
}
|
|
9134
|
-
);
|
|
9135
|
-
if (field.type === "boolean") {
|
|
9136
|
-
return /* @__PURE__ */ jsx9(
|
|
9137
|
-
SettingRow,
|
|
9138
|
-
{
|
|
9139
|
-
label: label(field.labelKey),
|
|
9140
|
-
description,
|
|
9141
|
-
badge: error ? t("common.error") : void 0,
|
|
9142
|
-
defaultKey,
|
|
9143
|
-
children: control
|
|
9144
|
-
}
|
|
9145
|
-
);
|
|
9146
|
-
}
|
|
9147
|
-
return /* @__PURE__ */ jsx9(DefaultsOnly, { settingKey: defaultKey ?? "", children: /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1.5 py-3 border-b border-border last:border-0 min-w-0", children: [
|
|
9148
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
|
|
9149
|
-
/* @__PURE__ */ jsx9("span", { className: "text-sm font-medium leading-snug", children: label(field.labelKey) }),
|
|
9150
|
-
error && /* @__PURE__ */ jsx9("span", { className: "text-[10px] font-bold text-warning border border-warning/40 px-1 shrink-0", children: t("common.error") }),
|
|
9151
|
-
defaultKey && /* @__PURE__ */ jsx9(HostDefaultBadge, { settingKey: defaultKey })
|
|
9152
|
-
] }),
|
|
9153
|
-
description && /* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground leading-snug", children: description }),
|
|
9154
|
-
/* @__PURE__ */ jsx9("div", { className: "min-w-0", children: control })
|
|
9155
|
-
] }) });
|
|
9156
|
-
}
|
|
9157
|
-
function FieldControl({
|
|
9158
|
-
pluginId,
|
|
9159
|
-
field,
|
|
9160
|
-
value,
|
|
9161
|
-
setValue,
|
|
9162
|
-
readOnly
|
|
9163
|
-
}) {
|
|
9164
|
-
const { t } = useTranslation4();
|
|
9165
|
-
const label = (key) => key ? t(pluginKey(pluginId, key)) : "";
|
|
9166
|
-
const placeholder = field.placeholderKey ? label(field.placeholderKey) : void 0;
|
|
9167
|
-
switch (field.type) {
|
|
9168
|
-
case "boolean":
|
|
9169
|
-
return /* @__PURE__ */ jsx9(
|
|
9170
|
-
FakeSwitch,
|
|
9171
|
-
{
|
|
9172
|
-
checked: value === true,
|
|
9173
|
-
disabled: readOnly,
|
|
9174
|
-
onChange: (next) => setValue(field.key, next)
|
|
9175
|
-
}
|
|
9176
|
-
);
|
|
9177
|
-
case "number":
|
|
9178
|
-
return /* @__PURE__ */ jsx9(
|
|
9179
|
-
Input,
|
|
9180
|
-
{
|
|
9181
|
-
type: "number",
|
|
9182
|
-
className: "h-8 w-full max-w-40 text-sm",
|
|
9183
|
-
disabled: readOnly,
|
|
9184
|
-
min: field.min,
|
|
9185
|
-
max: field.max,
|
|
9186
|
-
placeholder,
|
|
9187
|
-
value: value === void 0 || value === null ? "" : String(value),
|
|
9188
|
-
onChange: (event) => setValue(
|
|
9189
|
-
field.key,
|
|
9190
|
-
event.target.value === "" ? null : Number(event.target.value)
|
|
9191
|
-
)
|
|
9192
|
-
}
|
|
9193
|
-
);
|
|
9194
|
-
case "select":
|
|
9195
|
-
return /* @__PURE__ */ jsxs2(
|
|
9196
|
-
Select,
|
|
9197
|
-
{
|
|
9198
|
-
disabled: readOnly,
|
|
9199
|
-
value: typeof value === "string" ? value : "",
|
|
9200
|
-
onValueChange: (next) => setValue(field.key, next),
|
|
9201
|
-
children: [
|
|
9202
|
-
/* @__PURE__ */ jsx9(SelectTrigger, { className: "h-8 w-full min-w-0 text-sm", children: /* @__PURE__ */ jsx9(SelectValue, { placeholder }) }),
|
|
9203
|
-
/* @__PURE__ */ jsx9(SelectContent, { children: (field.options ?? []).map((option) => /* @__PURE__ */ jsx9(SelectItem, { value: option.value, children: label(option.labelKey) }, option.value)) })
|
|
9204
|
-
]
|
|
9205
|
-
}
|
|
9206
|
-
);
|
|
9207
|
-
case "multiselect": {
|
|
9208
|
-
const selected = Array.isArray(value) ? value : [];
|
|
9209
|
-
return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-1.5", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs2(
|
|
9210
|
-
"label",
|
|
9211
|
-
{
|
|
9212
|
-
className: "flex items-center gap-2 text-xs text-muted-foreground",
|
|
9213
|
-
children: [
|
|
9214
|
-
/* @__PURE__ */ jsx9(
|
|
9215
|
-
Checkbox2,
|
|
9216
|
-
{
|
|
9217
|
-
disabled: readOnly,
|
|
9218
|
-
checked: selected.includes(option.value),
|
|
9219
|
-
onCheckedChange: (checked) => setValue(
|
|
9220
|
-
field.key,
|
|
9221
|
-
checked ? [...selected, option.value] : selected.filter((entry) => entry !== option.value)
|
|
9222
|
-
)
|
|
9223
|
-
}
|
|
9224
|
-
),
|
|
9225
|
-
/* @__PURE__ */ jsx9("span", { children: label(option.labelKey) })
|
|
9226
|
-
]
|
|
9227
|
-
},
|
|
9228
|
-
option.value
|
|
9229
|
-
)) });
|
|
9230
|
-
}
|
|
9231
|
-
case "secret":
|
|
9232
|
-
return /* @__PURE__ */ jsx9(
|
|
9233
|
-
SecretControl,
|
|
9234
|
-
{
|
|
9235
|
-
field,
|
|
9236
|
-
value,
|
|
9237
|
-
setValue,
|
|
9238
|
-
readOnly,
|
|
9239
|
-
placeholder
|
|
9240
|
-
}
|
|
9241
|
-
);
|
|
9242
|
-
case "textarea":
|
|
9243
|
-
case "json":
|
|
9244
|
-
return /* @__PURE__ */ jsx9(
|
|
9245
|
-
Textarea,
|
|
9246
|
-
{
|
|
9247
|
-
className: "w-full text-sm font-mono min-h-16",
|
|
9248
|
-
disabled: readOnly,
|
|
9249
|
-
placeholder,
|
|
9250
|
-
value: typeof value === "string" ? value : value === void 0 || value === null ? "" : JSON.stringify(value, null, 2),
|
|
9251
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9252
|
-
}
|
|
9253
|
-
);
|
|
9254
|
-
default:
|
|
9255
|
-
return /* @__PURE__ */ jsx9(
|
|
9256
|
-
Input,
|
|
9257
|
-
{
|
|
9258
|
-
className: "h-8 w-full text-sm",
|
|
9259
|
-
disabled: readOnly,
|
|
9260
|
-
placeholder,
|
|
9261
|
-
value: typeof value === "string" ? value : "",
|
|
9262
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9263
|
-
}
|
|
9264
|
-
);
|
|
9265
|
-
}
|
|
9266
|
-
}
|
|
9267
|
-
function SecretControl({
|
|
9268
|
-
field,
|
|
9269
|
-
value,
|
|
9270
|
-
setValue,
|
|
9271
|
-
readOnly,
|
|
9272
|
-
placeholder
|
|
9273
|
-
}) {
|
|
9274
|
-
const { t } = useTranslation4();
|
|
9275
|
-
const redacted = isRedactedSecret(value);
|
|
9276
|
-
const stored = redacted && value.set;
|
|
9277
|
-
if (redacted) {
|
|
9278
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
9279
|
-
/* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: stored ? t("settings.secretSet") : t("settings.secretNotSet") }),
|
|
9280
|
-
/* @__PURE__ */ jsx9(
|
|
9281
|
-
Button,
|
|
9282
|
-
{
|
|
9283
|
-
variant: "outline",
|
|
9284
|
-
size: "sm",
|
|
9285
|
-
className: "h-7 text-xs",
|
|
9286
|
-
disabled: readOnly,
|
|
9287
|
-
onClick: () => setValue(field.key, ""),
|
|
9288
|
-
children: stored ? t("settings.secretReplace") : t("common.edit")
|
|
9289
|
-
}
|
|
9290
|
-
)
|
|
9291
|
-
] });
|
|
9292
|
-
}
|
|
9293
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
9294
|
-
/* @__PURE__ */ jsx9("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx9(
|
|
9295
|
-
PasswordInput,
|
|
9296
|
-
{
|
|
9297
|
-
className: "h-8 w-full text-sm",
|
|
9298
|
-
disabled: readOnly,
|
|
9299
|
-
placeholder,
|
|
9300
|
-
value: typeof value === "string" ? value : "",
|
|
9301
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9302
|
-
}
|
|
9303
|
-
) }),
|
|
9304
|
-
/* @__PURE__ */ jsx9(
|
|
9305
|
-
Button,
|
|
9306
|
-
{
|
|
9307
|
-
variant: "ghost",
|
|
9308
|
-
size: "sm",
|
|
9309
|
-
className: "h-7 text-xs",
|
|
9310
|
-
disabled: readOnly,
|
|
9311
|
-
onClick: () => setValue(field.key, { set: stored }),
|
|
9312
|
-
children: t("common.cancel")
|
|
9313
|
-
}
|
|
9314
|
-
)
|
|
9315
|
-
] });
|
|
9316
|
-
}
|
|
9317
|
-
|
|
9318
|
-
// src/ui/settings/HostPluginSections.tsx
|
|
9319
|
-
init_define_import_meta_env();
|
|
9320
|
-
import { useMemo as useMemo9 } from "react";
|
|
9321
|
-
import { useTranslation as useTranslation5 } from "react-i18next";
|
|
9322
|
-
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
9323
|
-
function usePluginHostSections() {
|
|
9324
|
-
const plugins = useInstalledPlugins();
|
|
9325
|
-
return useMemo9(
|
|
9326
|
-
() => plugins.filter((plugin) => {
|
|
9327
|
-
if (!plugin.enabled) return false;
|
|
9328
|
-
const host = plugin.contributes?.settings?.host;
|
|
9329
|
-
return !!host && (hasVisibleFields(host.fields) || !!host.enableKey);
|
|
9330
|
-
}),
|
|
9331
|
-
[plugins]
|
|
9332
|
-
);
|
|
9333
|
-
}
|
|
9334
|
-
function hostFieldDefaults(plugin) {
|
|
9335
|
-
const host = plugin.contributes?.settings?.host;
|
|
9336
|
-
if (!host) return {};
|
|
9337
|
-
const defaults3 = {};
|
|
9338
|
-
if (host.enableKey) defaults3[host.enableKey] = host.enableDefault ?? false;
|
|
9339
|
-
for (const field of host.fields) {
|
|
9340
|
-
if (field.default !== void 0) defaults3[field.key] = field.default;
|
|
9341
|
-
}
|
|
9342
|
-
return defaults3;
|
|
9343
|
-
}
|
|
9344
|
-
function HostPluginSections({
|
|
9345
|
-
plugins,
|
|
9346
|
-
values,
|
|
9347
|
-
setValue
|
|
9348
|
-
}) {
|
|
9349
|
-
if (plugins.length === 0) return null;
|
|
9350
|
-
return /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-2", children: plugins.map((plugin) => /* @__PURE__ */ jsx10(
|
|
9351
|
-
HostPluginSection,
|
|
9352
|
-
{
|
|
9353
|
-
plugin,
|
|
9354
|
-
values: values[plugin.id] ?? {},
|
|
9355
|
-
setValue: (key, value) => setValue(plugin.id, key, value)
|
|
9356
|
-
},
|
|
9357
|
-
plugin.id
|
|
9358
|
-
)) });
|
|
9359
|
-
}
|
|
9360
|
-
function HostFeatureFields({
|
|
9361
|
-
form,
|
|
9362
|
-
updateForm
|
|
9363
|
-
}) {
|
|
9364
|
-
const pluginId = usePluginScope();
|
|
9365
|
-
const plugin = usePluginHostSections().find((p) => p.id === pluginId);
|
|
9366
|
-
if (!plugin) return null;
|
|
9367
|
-
const values = form?.pluginSettings ?? {};
|
|
9368
|
-
return /* @__PURE__ */ jsx10(
|
|
9369
|
-
HostPluginSection,
|
|
9370
|
-
{
|
|
9371
|
-
plugin,
|
|
9372
|
-
values: values[plugin.id] ?? {},
|
|
9373
|
-
setValue: (key, value) => updateForm((current2) => {
|
|
9374
|
-
const all = current2.pluginSettings ?? {};
|
|
9375
|
-
return {
|
|
9376
|
-
...current2,
|
|
9377
|
-
pluginSettings: {
|
|
9378
|
-
...all,
|
|
9379
|
-
[plugin.id]: { ...all[plugin.id] ?? {}, [key]: value }
|
|
9380
|
-
}
|
|
9381
|
-
};
|
|
9382
|
-
})
|
|
9383
|
-
}
|
|
9384
|
-
);
|
|
9385
|
-
}
|
|
9386
|
-
function HostPluginSection({
|
|
9387
|
-
plugin,
|
|
9388
|
-
values,
|
|
9389
|
-
setValue
|
|
9390
|
-
}) {
|
|
9391
|
-
const { t } = useTranslation5();
|
|
9392
|
-
const host = plugin.contributes?.settings?.host;
|
|
9393
|
-
if (!host) return null;
|
|
9394
|
-
const shown = { ...hostFieldDefaults(plugin), ...values };
|
|
9395
|
-
const running = plugin.enabled && plugin.state !== "failed";
|
|
9396
|
-
const enableKey = host.enableKey;
|
|
9397
|
-
const enabled = enableKey ? shown[enableKey] === true : true;
|
|
9398
|
-
return /* @__PURE__ */ jsxs3(
|
|
9399
|
-
SectionCard,
|
|
9400
|
-
{
|
|
9401
|
-
title: pluginName(t, plugin),
|
|
9402
|
-
icon: /* @__PURE__ */ jsx10(PluginIcon, { name: plugin.icon, className: "size-3.5" }),
|
|
9403
|
-
action: /* @__PURE__ */ jsx10(DocsLink, { href: plugin.docs }),
|
|
9404
|
-
children: [
|
|
9405
|
-
!running && /* @__PURE__ */ jsx10("div", { className: "my-3 border border-warning/40 bg-warning/10 px-3 py-2 text-xs text-warning", children: t("settings.featureUnavailable", {
|
|
9406
|
-
name: pluginName(t, plugin)
|
|
9407
|
-
}) }),
|
|
9408
|
-
enableKey && /* @__PURE__ */ jsx10(
|
|
9409
|
-
SettingsFieldRow,
|
|
9410
|
-
{
|
|
9411
|
-
pluginId: plugin.id,
|
|
9412
|
-
field: {
|
|
9413
|
-
key: enableKey,
|
|
9414
|
-
type: "boolean",
|
|
9415
|
-
labelKey: host.enableLabelKey,
|
|
9416
|
-
descriptionKey: host.enableDescriptionKey
|
|
9417
|
-
},
|
|
9418
|
-
values: shown,
|
|
9419
|
-
setValue,
|
|
9420
|
-
running,
|
|
9421
|
-
defaultKey: `${plugin.id}.${enableKey}`
|
|
9422
|
-
}
|
|
9423
|
-
),
|
|
9424
|
-
enabled && host.fields.filter((field) => isFieldShown(field, shown)).map((field) => /* @__PURE__ */ jsx10(
|
|
9425
|
-
SettingsFieldRow,
|
|
9426
|
-
{
|
|
9427
|
-
pluginId: plugin.id,
|
|
9428
|
-
field,
|
|
9429
|
-
values: shown,
|
|
9430
|
-
setValue,
|
|
9431
|
-
running,
|
|
9432
|
-
defaultKey: `${plugin.id}.${field.key}`
|
|
9433
|
-
},
|
|
9434
|
-
field.key
|
|
9435
|
-
))
|
|
9436
|
-
]
|
|
9437
|
-
}
|
|
9438
|
-
);
|
|
9439
|
-
}
|
|
9440
|
-
|
|
9441
|
-
// src/ui/shell/ActionSlot.tsx
|
|
9442
|
-
init_define_import_meta_env();
|
|
9443
|
-
import React5 from "react";
|
|
9444
|
-
import { useTranslation as useTranslation6 } from "react-i18next";
|
|
9445
|
-
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9446
|
-
function ActionSlot({
|
|
9447
|
-
slotId,
|
|
9448
|
-
context,
|
|
9449
|
-
className,
|
|
9450
|
-
enabled = true,
|
|
9451
|
-
renderItem,
|
|
9452
|
-
hideLabels,
|
|
9453
|
-
when
|
|
9454
|
-
}) {
|
|
9455
|
-
const { t } = useTranslation6();
|
|
9456
|
-
const contributions2 = useActionSlot(slotId, when).filter(
|
|
9457
|
-
(contribution) => contribution.kind !== "component"
|
|
9458
|
-
);
|
|
9459
|
-
if (!enabled || contributions2.length === 0) return null;
|
|
9460
|
-
return /* @__PURE__ */ jsx11(Fragment2, { children: contributions2.map((contribution) => {
|
|
9461
|
-
const invoke = () => {
|
|
9462
|
-
void invokeAction(contribution.actionId, ...context?.() ?? []);
|
|
9463
|
-
};
|
|
9464
|
-
if (renderItem) {
|
|
9465
|
-
return /* @__PURE__ */ jsx11(React5.Fragment, { children: renderItem(contribution, invoke) }, contribution.actionId);
|
|
9466
|
-
}
|
|
9467
|
-
const Icon = contribution.icon;
|
|
9468
|
-
const label = t(contribution.titleKey);
|
|
9469
|
-
return /* @__PURE__ */ jsxs4(
|
|
9470
|
-
"button",
|
|
9471
|
-
{
|
|
9472
|
-
type: "button",
|
|
9473
|
-
className,
|
|
9474
|
-
"aria-label": label,
|
|
9475
|
-
title: label,
|
|
9476
|
-
onClick: invoke,
|
|
9477
|
-
children: [
|
|
9478
|
-
Icon && /* @__PURE__ */ jsx11(Icon, { className: "size-4 shrink-0" }),
|
|
9479
|
-
!hideLabels && label
|
|
9480
|
-
]
|
|
9481
|
-
},
|
|
9482
|
-
contribution.actionId
|
|
9483
|
-
);
|
|
9484
|
-
}) });
|
|
9485
|
-
}
|
|
9486
|
-
function ComponentSlot({
|
|
9487
|
-
slotId,
|
|
9488
|
-
props,
|
|
9489
|
-
when
|
|
9490
|
-
}) {
|
|
9491
|
-
const contributions2 = useActionSlot(slotId, when).filter(
|
|
9492
|
-
(contribution) => contribution.kind === "component" && contribution.component
|
|
9493
|
-
);
|
|
9494
|
-
if (contributions2.length === 0) return null;
|
|
9495
|
-
return /* @__PURE__ */ jsx11(Fragment2, { children: contributions2.map((contribution) => {
|
|
9496
|
-
const Contributed = contribution.component;
|
|
9497
|
-
return /* @__PURE__ */ jsx11(Contributed, { ...props ?? {} }, contribution.actionId);
|
|
9498
|
-
}) });
|
|
9499
|
-
}
|
|
9500
|
-
|
|
9501
|
-
// src/ui/shell/tab-handles.ts
|
|
9502
|
-
init_define_import_meta_env();
|
|
9503
|
-
import { useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
9504
|
-
var version3 = 0;
|
|
9505
|
-
var listeners8 = /* @__PURE__ */ new Set();
|
|
9506
|
-
var callbacks = /* @__PURE__ */ new WeakMap();
|
|
9507
|
-
function subscribe5(listener) {
|
|
9508
|
-
listeners8.add(listener);
|
|
9509
|
-
return () => listeners8.delete(listener);
|
|
9510
|
-
}
|
|
9511
|
-
function trackTabHandle(ref) {
|
|
9512
|
-
if (!ref) return void 0;
|
|
9513
|
-
let callback = callbacks.get(ref);
|
|
9514
|
-
if (!callback) {
|
|
9515
|
-
callback = (value) => {
|
|
9516
|
-
if (ref.current === value) return;
|
|
9517
|
-
ref.current = value;
|
|
9518
|
-
version3 += 1;
|
|
9519
|
-
for (const listener of listeners8) listener();
|
|
9520
|
-
};
|
|
9521
|
-
callbacks.set(ref, callback);
|
|
9522
|
-
}
|
|
9523
|
-
return callback;
|
|
9524
|
-
}
|
|
9525
|
-
function useTabHandlesVersion() {
|
|
9526
|
-
return useSyncExternalStore11(
|
|
9527
|
-
subscribe5,
|
|
9528
|
-
() => version3,
|
|
9529
|
-
() => version3
|
|
9530
|
-
);
|
|
9531
|
-
}
|
|
9532
|
-
|
|
9533
|
-
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
9534
|
-
init_define_import_meta_env();
|
|
9535
|
-
import { useTranslation as useTranslation7 } from "react-i18next";
|
|
9536
|
-
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
9537
|
-
function PluginViewPlaceholder({
|
|
9538
|
-
kind,
|
|
9539
|
-
viewId,
|
|
9540
|
-
compact = false
|
|
9541
|
-
}) {
|
|
9542
|
-
const { t } = useTranslation7();
|
|
9543
|
-
usePluginStore();
|
|
9544
|
-
const { has } = usePermissions();
|
|
9545
|
-
const { status, owner } = unregisteredViewStatus(kind, viewId);
|
|
9546
|
-
const name = owner ? pluginName(t, owner.summary) : viewId;
|
|
9547
|
-
if (status === "loading") {
|
|
9548
|
-
return /* @__PURE__ */ jsx12(
|
|
9549
|
-
"div",
|
|
9550
|
-
{
|
|
9551
|
-
className: "flex h-full w-full items-center justify-center",
|
|
9552
|
-
"aria-label": t("plugins.runtime.loading", { name }),
|
|
9553
|
-
children: /* @__PURE__ */ jsx12("div", { className: "size-5 rounded-full border-2 border-muted-foreground/30 border-t-muted-foreground/70 animate-spin" })
|
|
9554
|
-
}
|
|
9555
|
-
);
|
|
9556
|
-
}
|
|
9557
|
-
const title = status === "failed" ? t("plugins.runtime.failed", { name }) : owner ? t("plugins.runtime.needsPlugin", { name }) : t("plugins.runtime.needsUnknownPlugin");
|
|
9558
|
-
const hint = status === "failed" ? t("plugins.runtime.failedHint") : status === "disabled" ? t("plugins.runtime.disabledHint") : t("plugins.runtime.missingHint");
|
|
9559
|
-
return /* @__PURE__ */ jsxs5(
|
|
9560
|
-
"div",
|
|
9561
|
-
{
|
|
9562
|
-
"data-testid": "plugin-view-placeholder",
|
|
9563
|
-
"data-status": status,
|
|
9564
|
-
className: `flex h-full w-full flex-col items-center justify-center gap-2 text-center ${compact ? "p-3" : "p-6"}`,
|
|
9565
|
-
children: [
|
|
9566
|
-
/* @__PURE__ */ jsx12(CircleSlash, { className: "size-6 text-muted-foreground/40" }),
|
|
9567
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm font-semibold text-muted-foreground", children: title }),
|
|
9568
|
-
/* @__PURE__ */ jsx12("span", { className: "text-xs text-muted-foreground/70", children: hint }),
|
|
9569
|
-
!compact && status !== "failed" && has("admin.plugins.manage") && /* @__PURE__ */ jsx12(
|
|
9570
|
-
Button,
|
|
9571
|
-
{
|
|
9572
|
-
variant: "outline",
|
|
9573
|
-
size: "sm",
|
|
9574
|
-
className: "mt-1",
|
|
9575
|
-
onClick: () => window.dispatchEvent(new CustomEvent(OPEN_PLUGINS_EVENT)),
|
|
9576
|
-
children: t("plugins.manager.browsePlugins")
|
|
9577
|
-
}
|
|
9578
|
-
)
|
|
9579
|
-
]
|
|
9580
|
-
}
|
|
9581
|
-
);
|
|
9582
|
-
}
|
|
9583
|
-
|
|
9584
|
-
// src/ui/lib/adaptive-resource-budget.ts
|
|
9585
|
-
init_define_import_meta_env();
|
|
9586
|
-
|
|
9587
|
-
// src/ui/lib/local-adaptive-engine.ts
|
|
9588
|
-
init_define_import_meta_env();
|
|
9589
|
-
var LOCAL_ADAPTIVE_ENGINE_KEY = "termix.local.adaptive-engine.v1";
|
|
9590
|
-
var VERSION = 1;
|
|
9591
|
-
var HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9592
|
-
var MAX_SCOPES = 128;
|
|
9593
|
-
var MAX_ACTIONS_PER_SCOPE = 12;
|
|
9594
|
-
var DEFAULT_MIN_EVIDENCE = 2.5;
|
|
9595
|
-
var DEFAULT_MIN_SHARE = 0.6;
|
|
9596
|
-
var DEFAULT_MIN_MARGIN = 1;
|
|
9597
|
-
var EWMA_ALPHA = 0.25;
|
|
9598
|
-
function emptyStore() {
|
|
9599
|
-
return { version: VERSION, scopes: {} };
|
|
9600
|
-
}
|
|
9601
|
-
function finiteNonNegative(value) {
|
|
9602
|
-
return Number.isFinite(value) && Number(value) >= 0 ? Number(value) : 0;
|
|
9603
|
-
}
|
|
9604
|
-
function sanitizeAction(value) {
|
|
9605
|
-
if (!value || typeof value !== "object") return null;
|
|
9606
|
-
const stat = value;
|
|
9607
|
-
if (!Number.isFinite(stat.weight) || Number(stat.weight) < 0 || !Number.isFinite(stat.updatedAt)) {
|
|
9608
|
-
return null;
|
|
9609
|
-
}
|
|
9610
|
-
const latencyEwmaMs = finiteNonNegative(stat.latencyEwmaMs);
|
|
9611
|
-
return {
|
|
9612
|
-
weight: Number(stat.weight),
|
|
9613
|
-
updatedAt: Number(stat.updatedAt),
|
|
9614
|
-
observations: finiteNonNegative(stat.observations),
|
|
9615
|
-
successes: finiteNonNegative(stat.successes),
|
|
9616
|
-
cancellations: finiteNonNegative(stat.cancellations),
|
|
9617
|
-
fallbacks: finiteNonNegative(stat.fallbacks),
|
|
9618
|
-
...latencyEwmaMs > 0 ? { latencyEwmaMs } : {}
|
|
9619
|
-
};
|
|
9620
|
-
}
|
|
9621
|
-
function sanitizeStore(value) {
|
|
9622
|
-
if (!value || typeof value !== "object") return emptyStore();
|
|
9623
|
-
const candidate = value;
|
|
9624
|
-
if (candidate.version !== VERSION || !candidate.scopes || typeof candidate.scopes !== "object" || Array.isArray(candidate.scopes)) {
|
|
9625
|
-
return emptyStore();
|
|
9626
|
-
}
|
|
9627
|
-
const scopes2 = {};
|
|
9628
|
-
for (const [scope, rawScope] of Object.entries(candidate.scopes)) {
|
|
9629
|
-
if (!rawScope || typeof rawScope !== "object") continue;
|
|
9630
|
-
const value2 = rawScope;
|
|
9631
|
-
if (!Number.isFinite(value2.updatedAt) || !value2.actions || typeof value2.actions !== "object" || Array.isArray(value2.actions)) {
|
|
9632
|
-
continue;
|
|
9633
|
-
}
|
|
9634
|
-
const actions4 = {};
|
|
9635
|
-
for (const [action, rawStat] of Object.entries(value2.actions)) {
|
|
9636
|
-
const stat = sanitizeAction(rawStat);
|
|
9637
|
-
if (stat) actions4[action] = stat;
|
|
9638
|
-
}
|
|
9639
|
-
scopes2[scope] = { actions: actions4, updatedAt: Number(value2.updatedAt) };
|
|
9640
|
-
}
|
|
9641
|
-
return { version: VERSION, scopes: scopes2 };
|
|
9642
|
-
}
|
|
9643
|
-
function readStore() {
|
|
9644
|
-
if (typeof localStorage === "undefined") return emptyStore();
|
|
9645
|
-
try {
|
|
9646
|
-
return sanitizeStore(
|
|
9647
|
-
JSON.parse(localStorage.getItem(LOCAL_ADAPTIVE_ENGINE_KEY) ?? "null")
|
|
9648
|
-
);
|
|
9649
|
-
} catch {
|
|
9650
|
-
return emptyStore();
|
|
9651
|
-
}
|
|
9652
|
-
}
|
|
9653
|
-
function writeStore(store) {
|
|
9654
|
-
if (typeof localStorage === "undefined") return;
|
|
9655
|
-
try {
|
|
9656
|
-
localStorage.setItem(LOCAL_ADAPTIVE_ENGINE_KEY, JSON.stringify(store));
|
|
9657
|
-
} catch {
|
|
9658
|
-
}
|
|
9659
|
-
}
|
|
9660
|
-
function decayedWeight(stat, now) {
|
|
9661
|
-
const age = Math.max(0, now - stat.updatedAt);
|
|
9662
|
-
return stat.weight * 2 ** (-age / HALF_LIFE_MS);
|
|
9663
|
-
}
|
|
9664
|
-
function trimStore(store, now) {
|
|
9665
|
-
for (const scope of Object.values(store.scopes)) {
|
|
9666
|
-
scope.actions = Object.fromEntries(
|
|
9667
|
-
Object.entries(scope.actions).sort(
|
|
9668
|
-
([, a], [, b]) => decayedWeight(b, now) - decayedWeight(a, now) || b.updatedAt - a.updatedAt
|
|
9669
|
-
).slice(0, MAX_ACTIONS_PER_SCOPE)
|
|
9670
|
-
);
|
|
9671
|
-
}
|
|
9672
|
-
store.scopes = Object.fromEntries(
|
|
9673
|
-
Object.entries(store.scopes).sort(([, a], [, b]) => b.updatedAt - a.updatedAt).slice(0, MAX_SCOPES)
|
|
9674
|
-
);
|
|
9675
|
-
}
|
|
9676
|
-
function updateEwma(previous, value) {
|
|
9677
|
-
return previous === void 0 ? value : previous + EWMA_ALPHA * (value - previous);
|
|
9678
|
-
}
|
|
9679
|
-
function getActionStats(store, scope, action, now) {
|
|
9680
|
-
const scopeStats = store.scopes[scope] ?? { actions: {}, updatedAt: now };
|
|
9681
|
-
return [
|
|
9682
|
-
scopeStats,
|
|
9683
|
-
scopeStats.actions[action] ?? {
|
|
9684
|
-
weight: 0,
|
|
9685
|
-
updatedAt: now,
|
|
9686
|
-
observations: 0,
|
|
9687
|
-
successes: 0,
|
|
9688
|
-
cancellations: 0,
|
|
9689
|
-
fallbacks: 0
|
|
9690
|
-
}
|
|
9691
|
-
];
|
|
9692
|
-
}
|
|
9693
|
-
function saveActionStats(store, scope, action, scopeStats, actionStats, now) {
|
|
9694
|
-
scopeStats.actions[action] = actionStats;
|
|
9695
|
-
scopeStats.updatedAt = now;
|
|
9696
|
-
store.scopes[scope] = scopeStats;
|
|
9697
|
-
trimStore(store, now);
|
|
9698
|
-
writeStore(store);
|
|
9699
|
-
}
|
|
9700
|
-
function recordLocalAdaptiveChoice(scope, action, now = Date.now()) {
|
|
9701
|
-
if (!scope || !action) return;
|
|
9702
|
-
const store = readStore();
|
|
9703
|
-
const [scopeStats, previous] = getActionStats(store, scope, action, now);
|
|
9704
|
-
saveActionStats(
|
|
9705
|
-
store,
|
|
9706
|
-
scope,
|
|
9707
|
-
action,
|
|
9708
|
-
scopeStats,
|
|
9709
|
-
{
|
|
9710
|
-
...previous,
|
|
9711
|
-
weight: decayedWeight(previous, now) + 1,
|
|
9712
|
-
updatedAt: now
|
|
9713
|
-
},
|
|
9714
|
-
now
|
|
9715
|
-
);
|
|
9716
|
-
}
|
|
9717
|
-
function recordLocalAdaptiveOutcome(scope, action, outcome, now = Date.now()) {
|
|
9718
|
-
if (!scope || !action || !Object.values(outcome).some((v) => v !== void 0)) {
|
|
9719
|
-
return;
|
|
9720
|
-
}
|
|
9721
|
-
const store = readStore();
|
|
9722
|
-
const [scopeStats, previous] = getActionStats(store, scope, action, now);
|
|
9723
|
-
const latency = finiteNonNegative(outcome.latencyMs);
|
|
9724
|
-
saveActionStats(
|
|
9725
|
-
store,
|
|
9726
|
-
scope,
|
|
9727
|
-
action,
|
|
9728
|
-
scopeStats,
|
|
9729
|
-
{
|
|
9730
|
-
...previous,
|
|
9731
|
-
updatedAt: now,
|
|
9732
|
-
observations: previous.observations + 1,
|
|
9733
|
-
successes: previous.successes + (outcome.success === true ? 1 : 0),
|
|
9734
|
-
cancellations: previous.cancellations + (outcome.cancelled === true ? 1 : 0),
|
|
9735
|
-
fallbacks: previous.fallbacks + (outcome.fallback === true ? 1 : 0),
|
|
9736
|
-
...latency > 0 ? { latencyEwmaMs: updateEwma(previous.latencyEwmaMs, latency) } : {}
|
|
9737
|
-
},
|
|
9738
|
-
now
|
|
9739
|
-
);
|
|
9740
|
-
}
|
|
9741
|
-
function chooseLocalAdaptiveAction({
|
|
9742
|
-
scope,
|
|
9743
|
-
candidates,
|
|
9744
|
-
fallback,
|
|
9745
|
-
now = Date.now(),
|
|
9746
|
-
ttlMs = 5 * 60 * 1e3,
|
|
9747
|
-
minEvidence = DEFAULT_MIN_EVIDENCE,
|
|
9748
|
-
minShare = DEFAULT_MIN_SHARE,
|
|
9749
|
-
minMargin = DEFAULT_MIN_MARGIN
|
|
9750
|
-
}) {
|
|
9751
|
-
const expiresAt = now + Math.max(0, ttlMs);
|
|
9752
|
-
const stats = readStore().scopes[scope]?.actions;
|
|
9753
|
-
if (!stats || candidates.length === 0) {
|
|
9754
|
-
return { action: fallback, confidence: 0, reason: "fallback", expiresAt };
|
|
9755
|
-
}
|
|
9756
|
-
const ranked = candidates.map((action) => ({
|
|
9757
|
-
action,
|
|
9758
|
-
weight: stats[action] ? decayedWeight(stats[action], now) : 0
|
|
9759
|
-
})).sort((a, b) => b.weight - a.weight);
|
|
9760
|
-
const total = ranked.reduce((sum, item) => sum + item.weight, 0);
|
|
9761
|
-
const [best, second] = ranked;
|
|
9762
|
-
if (!best || total <= 0) {
|
|
9763
|
-
return { action: fallback, confidence: 0, reason: "fallback", expiresAt };
|
|
9764
|
-
}
|
|
9765
|
-
const share = best.weight / total;
|
|
9766
|
-
const margin = best.weight - (second?.weight ?? 0);
|
|
9767
|
-
const confidence = Math.min(
|
|
9768
|
-
1,
|
|
9769
|
-
best.weight / Math.max(minEvidence, Number.EPSILON),
|
|
9770
|
-
share / Math.max(minShare, Number.EPSILON),
|
|
9771
|
-
margin / Math.max(minMargin, Number.EPSILON)
|
|
9772
|
-
);
|
|
9773
|
-
const learned = best.weight >= minEvidence && share >= minShare && margin >= minMargin;
|
|
9774
|
-
return {
|
|
9775
|
-
action: learned ? best.action : fallback,
|
|
9776
|
-
confidence,
|
|
9777
|
-
reason: learned ? "learned" : "insufficient-evidence",
|
|
9778
|
-
expiresAt
|
|
9779
|
-
};
|
|
9780
|
-
}
|
|
9781
|
-
function getLocalAdaptiveStats(scope) {
|
|
9782
|
-
return readStore().scopes[scope]?.actions ?? {};
|
|
9783
|
-
}
|
|
9784
|
-
function clearLocalAdaptiveEngine() {
|
|
9785
|
-
if (typeof localStorage === "undefined") return;
|
|
9786
|
-
try {
|
|
9787
|
-
localStorage.removeItem(LOCAL_ADAPTIVE_ENGINE_KEY);
|
|
9788
|
-
} catch {
|
|
9789
|
-
}
|
|
9790
|
-
}
|
|
9791
|
-
|
|
9792
|
-
// src/ui/lib/adaptive-resource-budget.ts
|
|
9793
|
-
var scopes = {
|
|
9794
|
-
module: "resource-budget:module",
|
|
9795
|
-
network: "resource-budget:network"
|
|
9796
|
-
};
|
|
9797
|
-
var usefulnessScopes = {
|
|
9798
|
-
module: "resource-usefulness:module",
|
|
9799
|
-
network: "resource-usefulness:network"
|
|
9800
|
-
};
|
|
9801
|
-
var PRELOAD_USE_WINDOW_MS = 1e4;
|
|
9802
|
-
var pendingPreloads = /* @__PURE__ */ new Map();
|
|
9803
|
-
var activeTasks = {
|
|
9804
|
-
module: 0,
|
|
9805
|
-
network: 0
|
|
9806
|
-
};
|
|
9807
|
-
var budgets = {
|
|
9808
|
-
paused: {
|
|
9809
|
-
tier: "paused",
|
|
9810
|
-
allowModulePreload: false,
|
|
9811
|
-
allowNetworkPrefetch: false,
|
|
9812
|
-
maxPrefetchBytes: 0,
|
|
9813
|
-
maxConcurrentModulePreloads: 0,
|
|
9814
|
-
maxConcurrentNetworkPrefetches: 0,
|
|
9815
|
-
reason: "hidden"
|
|
9816
|
-
},
|
|
9817
|
-
constrained: {
|
|
9818
|
-
tier: "constrained",
|
|
9819
|
-
allowModulePreload: false,
|
|
9820
|
-
allowNetworkPrefetch: false,
|
|
9821
|
-
maxPrefetchBytes: 0,
|
|
9822
|
-
maxConcurrentModulePreloads: 0,
|
|
9823
|
-
maxConcurrentNetworkPrefetches: 0,
|
|
9824
|
-
reason: "environment"
|
|
9825
|
-
},
|
|
9826
|
-
balanced: {
|
|
9827
|
-
tier: "balanced",
|
|
9828
|
-
allowModulePreload: true,
|
|
9829
|
-
allowNetworkPrefetch: true,
|
|
9830
|
-
maxPrefetchBytes: 128 * 1024,
|
|
9831
|
-
maxConcurrentModulePreloads: 1,
|
|
9832
|
-
maxConcurrentNetworkPrefetches: 1,
|
|
9833
|
-
reason: "environment"
|
|
9834
|
-
},
|
|
9835
|
-
eager: {
|
|
9836
|
-
tier: "eager",
|
|
9837
|
-
allowModulePreload: true,
|
|
9838
|
-
allowNetworkPrefetch: true,
|
|
9839
|
-
maxPrefetchBytes: 512 * 1024,
|
|
9840
|
-
maxConcurrentModulePreloads: 2,
|
|
9841
|
-
maxConcurrentNetworkPrefetches: 2,
|
|
9842
|
-
reason: "default"
|
|
9843
|
-
}
|
|
9844
|
-
};
|
|
9845
|
-
function withReason(tier, reason) {
|
|
9846
|
-
return { ...budgets[tier], reason };
|
|
9847
|
-
}
|
|
9848
|
-
function feedbackIsPoor(feedback) {
|
|
9849
|
-
if (!feedback || feedback.observations < 4) return false;
|
|
9850
|
-
const failureRate = 1 - feedback.successes / feedback.observations;
|
|
9851
|
-
const abandoned = feedback.cancellations + feedback.fallbacks;
|
|
9852
|
-
return failureRate > 0.25 || abandoned / feedback.observations > 0.25 || (feedback.latencyEwmaMs ?? 0) > 2e3 || (feedback.usefulnessObservations ?? 0) >= 4 && (feedback.usefulPreloads ?? 0) / (feedback.usefulnessObservations ?? 1) < 0.25;
|
|
9853
|
-
}
|
|
9854
|
-
function preloadKey(kind, action) {
|
|
9855
|
-
return `${kind}:${action}`;
|
|
9856
|
-
}
|
|
9857
|
-
function flushExpiredPreloads(now = Date.now()) {
|
|
9858
|
-
for (const [key, preload] of pendingPreloads) {
|
|
9859
|
-
if (preload.expiresAt > now) continue;
|
|
9860
|
-
recordLocalAdaptiveOutcome(usefulnessScopes[preload.kind], preload.action, {
|
|
9861
|
-
success: false
|
|
9862
|
-
});
|
|
9863
|
-
pendingPreloads.delete(key);
|
|
9864
|
-
}
|
|
9865
|
-
}
|
|
9866
|
-
function markAdaptiveResourceUsed(kind, action, now = Date.now()) {
|
|
9867
|
-
flushExpiredPreloads(now);
|
|
9868
|
-
const key = preloadKey(kind, action);
|
|
9869
|
-
if (!pendingPreloads.has(key)) return;
|
|
9870
|
-
pendingPreloads.delete(key);
|
|
9871
|
-
recordLocalAdaptiveOutcome(
|
|
9872
|
-
usefulnessScopes[kind],
|
|
9873
|
-
action,
|
|
9874
|
-
{ success: true },
|
|
9875
|
-
now
|
|
9876
|
-
);
|
|
9877
|
-
}
|
|
9878
|
-
function computeAdaptiveResourceBudget(environment, feedback) {
|
|
9879
|
-
if (!environment.visible) return withReason("paused", "hidden");
|
|
9880
|
-
if (environment.saveData || ["slow-2g", "2g", "3g"].includes(environment.effectiveType ?? "")) {
|
|
9881
|
-
return withReason("constrained", "environment");
|
|
9882
|
-
}
|
|
9883
|
-
const limitedDevice = (environment.deviceMemoryGb ?? 8) <= 4 || (environment.hardwareConcurrency ?? 8) <= 4;
|
|
9884
|
-
const baseline = limitedDevice ? "balanced" : "eager";
|
|
9885
|
-
if (!feedbackIsPoor(feedback)) {
|
|
9886
|
-
return withReason(baseline, limitedDevice ? "environment" : "default");
|
|
9887
|
-
}
|
|
9888
|
-
return withReason(
|
|
9889
|
-
baseline === "eager" ? "balanced" : "constrained",
|
|
9890
|
-
"feedback"
|
|
9891
|
-
);
|
|
9892
|
-
}
|
|
9893
|
-
function readEnvironment() {
|
|
9894
|
-
const navigatorLike = typeof navigator === "undefined" ? void 0 : navigator;
|
|
9895
|
-
return {
|
|
9896
|
-
visible: typeof document === "undefined" || document.visibilityState !== "hidden",
|
|
9897
|
-
saveData: navigatorLike?.connection?.saveData,
|
|
9898
|
-
effectiveType: navigatorLike?.connection?.effectiveType,
|
|
9899
|
-
deviceMemoryGb: navigatorLike?.deviceMemory,
|
|
9900
|
-
hardwareConcurrency: navigatorLike?.hardwareConcurrency
|
|
9901
|
-
};
|
|
9902
|
-
}
|
|
9903
|
-
function readFeedback(kind) {
|
|
9904
|
-
flushExpiredPreloads();
|
|
9905
|
-
const stats = Object.values(getLocalAdaptiveStats(scopes[kind]));
|
|
9906
|
-
const usefulness = Object.values(
|
|
9907
|
-
getLocalAdaptiveStats(usefulnessScopes[kind])
|
|
9908
|
-
);
|
|
9909
|
-
const observations = stats.reduce((sum, stat) => sum + stat.observations, 0);
|
|
9910
|
-
const latencySamples = stats.filter(
|
|
9911
|
-
(stat) => stat.latencyEwmaMs !== void 0 && stat.observations > 0
|
|
9912
|
-
);
|
|
9913
|
-
const latencyWeight = latencySamples.reduce(
|
|
9914
|
-
(sum, stat) => sum + stat.observations,
|
|
9915
|
-
0
|
|
9916
|
-
);
|
|
9917
|
-
return {
|
|
9918
|
-
observations,
|
|
9919
|
-
successes: stats.reduce((sum, stat) => sum + stat.successes, 0),
|
|
9920
|
-
cancellations: stats.reduce((sum, stat) => sum + stat.cancellations, 0),
|
|
9921
|
-
fallbacks: stats.reduce((sum, stat) => sum + stat.fallbacks, 0),
|
|
9922
|
-
usefulnessObservations: usefulness.reduce(
|
|
9923
|
-
(sum, stat) => sum + stat.observations,
|
|
9924
|
-
0
|
|
9925
|
-
),
|
|
9926
|
-
usefulPreloads: usefulness.reduce((sum, stat) => sum + stat.successes, 0),
|
|
9927
|
-
...latencyWeight > 0 ? {
|
|
9928
|
-
latencyEwmaMs: latencySamples.reduce(
|
|
9929
|
-
(sum, stat) => sum + (stat.latencyEwmaMs ?? 0) * stat.observations,
|
|
9930
|
-
0
|
|
9931
|
-
) / latencyWeight
|
|
9932
|
-
} : {}
|
|
9933
|
-
};
|
|
9934
|
-
}
|
|
9935
|
-
function getAdaptiveResourceBudget(kind) {
|
|
9936
|
-
return computeAdaptiveResourceBudget(readEnvironment(), readFeedback(kind));
|
|
9937
|
-
}
|
|
9938
|
-
function runAdaptiveBackgroundTask(kind, action, task, options = {}) {
|
|
9939
|
-
const budget = getAdaptiveResourceBudget(kind);
|
|
9940
|
-
const allowed = kind === "module" ? budget.allowModulePreload : budget.allowNetworkPrefetch && (options.estimatedBytes === void 0 || options.estimatedBytes <= budget.maxPrefetchBytes);
|
|
9941
|
-
const concurrency = kind === "module" ? budget.maxConcurrentModulePreloads : budget.maxConcurrentNetworkPrefetches;
|
|
9942
|
-
if (!allowed || activeTasks[kind] >= concurrency) return false;
|
|
9943
|
-
activeTasks[kind] += 1;
|
|
9944
|
-
const key = preloadKey(kind, action);
|
|
9945
|
-
pendingPreloads.set(key, {
|
|
9946
|
-
kind,
|
|
9947
|
-
action,
|
|
9948
|
-
expiresAt: Date.now() + PRELOAD_USE_WINDOW_MS
|
|
9949
|
-
});
|
|
9950
|
-
const startedAt = performance.now();
|
|
9951
|
-
void Promise.resolve().then(task).then(
|
|
9952
|
-
() => {
|
|
9953
|
-
activeTasks[kind] -= 1;
|
|
9954
|
-
recordLocalAdaptiveOutcome(scopes[kind], action, {
|
|
9955
|
-
success: true,
|
|
9956
|
-
latencyMs: performance.now() - startedAt
|
|
9957
|
-
});
|
|
9958
|
-
},
|
|
9959
|
-
() => {
|
|
9960
|
-
activeTasks[kind] -= 1;
|
|
9961
|
-
pendingPreloads.delete(key);
|
|
9962
|
-
recordLocalAdaptiveOutcome(scopes[kind], action, {
|
|
9963
|
-
success: false,
|
|
9964
|
-
latencyMs: performance.now() - startedAt
|
|
9965
|
-
});
|
|
9966
|
-
}
|
|
9967
|
-
);
|
|
9968
|
-
return true;
|
|
9969
|
-
}
|
|
9970
|
-
|
|
9971
|
-
// src/ui/shell/tabUtils.tsx
|
|
9972
|
-
init_define_import_meta_env();
|
|
9973
|
-
import { lazy, memo as memo2, Suspense } from "react";
|
|
9974
|
-
import { useTranslation as useTranslation9 } from "react-i18next";
|
|
9975
|
-
|
|
9976
8972
|
// src/ui/lib/host-to-ssh-host.ts
|
|
9977
8973
|
init_define_import_meta_env();
|
|
9978
8974
|
function hostToSSHHost(h) {
|
|
@@ -10009,446 +9005,7 @@ function hostToSSHHost(h) {
|
|
|
10009
9005
|
};
|
|
10010
9006
|
}
|
|
10011
9007
|
|
|
10012
|
-
// src/ui/shell/CompanionFrame.tsx
|
|
10013
|
-
init_define_import_meta_env();
|
|
10014
|
-
import {
|
|
10015
|
-
memo,
|
|
10016
|
-
useCallback as useCallback9,
|
|
10017
|
-
useEffect as useEffect18,
|
|
10018
|
-
useMemo as useMemo10,
|
|
10019
|
-
useRef as useRef8,
|
|
10020
|
-
useState as useState16
|
|
10021
|
-
} from "react";
|
|
10022
|
-
import { useTranslation as useTranslation8 } from "react-i18next";
|
|
10023
|
-
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
10024
|
-
var DEFAULT_SIDE_SIZE = 360;
|
|
10025
|
-
var DEFAULT_BOTTOM_SIZE = 280;
|
|
10026
|
-
var MIN_SIZE = 200;
|
|
10027
|
-
function DefaultsReader({
|
|
10028
|
-
def,
|
|
10029
|
-
onValue
|
|
10030
|
-
}) {
|
|
10031
|
-
const Reader = def.Defaults;
|
|
10032
|
-
const report = useCallback9(
|
|
10033
|
-
(value) => onValue(def.id, value),
|
|
10034
|
-
[def.id, onValue]
|
|
10035
|
-
);
|
|
10036
|
-
return Reader ? /* @__PURE__ */ jsx13(Reader, { onValue: report }) : null;
|
|
10037
|
-
}
|
|
10038
|
-
function sideIcon(side) {
|
|
10039
|
-
if (side === "left") return ArrowLeftToLine;
|
|
10040
|
-
if (side === "bottom") return ArrowDownToLine;
|
|
10041
|
-
return ArrowRightToLine;
|
|
10042
|
-
}
|
|
10043
|
-
var CompanionFrame = memo(function CompanionFrame2({
|
|
10044
|
-
tab,
|
|
10045
|
-
isVisible,
|
|
10046
|
-
children
|
|
10047
|
-
}) {
|
|
10048
|
-
const defs = useCompanionDefs();
|
|
10049
|
-
const layoutDefs = useCompanionLayoutDefs();
|
|
10050
|
-
const applicable = useMemo10(
|
|
10051
|
-
() => arrangeCompanions(
|
|
10052
|
-
defs.filter((def) => companionApplies(def, tab)),
|
|
10053
|
-
resolveCompanionLayout(tab.type, tab.host).order
|
|
10054
|
-
),
|
|
10055
|
-
// tab.host and tab.type decide it
|
|
10056
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10057
|
-
[defs, layoutDefs, tab.type, tab.host]
|
|
10058
|
-
);
|
|
10059
|
-
if (applicable.length === 0) return /* @__PURE__ */ jsx13(Fragment3, { children });
|
|
10060
|
-
return /* @__PURE__ */ jsx13(CompanionLayout, { tab, defs: applicable, isVisible, children });
|
|
10061
|
-
});
|
|
10062
|
-
function CompanionLayout({
|
|
10063
|
-
tab,
|
|
10064
|
-
defs,
|
|
10065
|
-
isVisible,
|
|
10066
|
-
children
|
|
10067
|
-
}) {
|
|
10068
|
-
const { t } = useTranslation8();
|
|
10069
|
-
const isMobile = useIsMobile();
|
|
10070
|
-
const key = companionKey(tab);
|
|
10071
|
-
const state2 = useCompanionState(key);
|
|
10072
|
-
const [defaults3, setDefaults] = useState16(
|
|
10073
|
-
{}
|
|
10074
|
-
);
|
|
10075
|
-
const [dragging, setDragging] = useState16(false);
|
|
10076
|
-
const [mounted, setMounted] = useState16(/* @__PURE__ */ new Set());
|
|
10077
|
-
const rootRef = useRef8(null);
|
|
10078
|
-
const onDefaults = useCallback9((id, value) => {
|
|
10079
|
-
setDefaults((prev) => {
|
|
10080
|
-
const old = prev[id];
|
|
10081
|
-
if (old && old.open === value.open && old.side === value.side && old.size === value.size && old.edgeButton === value.edgeButton) {
|
|
10082
|
-
return prev;
|
|
10083
|
-
}
|
|
10084
|
-
return { ...prev, [id]: value };
|
|
10085
|
-
});
|
|
10086
|
-
}, []);
|
|
10087
|
-
useEffect18(() => {
|
|
10088
|
-
if (state2.seen || !isVisible) return;
|
|
10089
|
-
const ready = defs.every(
|
|
10090
|
-
(def) => !def.Defaults || defaults3[def.id] !== void 0
|
|
10091
|
-
);
|
|
10092
|
-
if (!ready) return;
|
|
10093
|
-
const auto = defs.find((def) => defaults3[def.id]?.open);
|
|
10094
|
-
patchCompanionState(key, { seen: true, openId: auto?.id ?? null });
|
|
10095
|
-
}, [state2.seen, isVisible, defs, defaults3, key]);
|
|
10096
|
-
const active = defs.find((def) => def.id === state2.openId) ?? null;
|
|
10097
|
-
useEffect18(() => {
|
|
10098
|
-
if (!active) return;
|
|
10099
|
-
setMounted(
|
|
10100
|
-
(prev) => prev.has(active.id) ? prev : new Set(prev).add(active.id)
|
|
10101
|
-
);
|
|
10102
|
-
}, [active]);
|
|
10103
|
-
const activeDefaults = active ? defaults3[active.id] : void 0;
|
|
10104
|
-
const layout = useMemo10(
|
|
10105
|
-
() => resolveCompanionLayout(tab.type, tab.host),
|
|
10106
|
-
[tab.type, tab.host]
|
|
10107
|
-
);
|
|
10108
|
-
const side = isMobile ? "bottom" : state2.side ?? layout.side ?? activeDefaults?.side ?? "right";
|
|
10109
|
-
const baseSize = state2.size ?? activeDefaults?.size ?? (side === "bottom" ? DEFAULT_BOTTOM_SIZE : DEFAULT_SIDE_SIZE);
|
|
10110
|
-
const setSide = useCallback9(
|
|
10111
|
-
(next) => patchCompanionState(key, { side: next }),
|
|
10112
|
-
[key]
|
|
10113
|
-
);
|
|
10114
|
-
const close = useCallback9(
|
|
10115
|
-
() => patchCompanionState(key, { openId: null }),
|
|
10116
|
-
[key]
|
|
10117
|
-
);
|
|
10118
|
-
const startResize = (event) => {
|
|
10119
|
-
event.preventDefault();
|
|
10120
|
-
const root = rootRef.current;
|
|
10121
|
-
if (!root) return;
|
|
10122
|
-
const rect = root.getBoundingClientRect();
|
|
10123
|
-
const total = side === "bottom" ? rect.height : rect.width;
|
|
10124
|
-
const max = Math.max(MIN_SIZE, total - MIN_SIZE);
|
|
10125
|
-
setDragging(true);
|
|
10126
|
-
const move = (e) => {
|
|
10127
|
-
const raw = side === "right" ? rect.right - e.clientX : side === "left" ? e.clientX - rect.left : rect.bottom - e.clientY;
|
|
10128
|
-
patchCompanionState(key, {
|
|
10129
|
-
size: Math.round(Math.min(max, Math.max(MIN_SIZE, raw)))
|
|
10130
|
-
});
|
|
10131
|
-
};
|
|
10132
|
-
const up = () => {
|
|
10133
|
-
setDragging(false);
|
|
10134
|
-
window.removeEventListener("mousemove", move);
|
|
10135
|
-
window.removeEventListener("mouseup", up);
|
|
10136
|
-
};
|
|
10137
|
-
window.addEventListener("mousemove", move);
|
|
10138
|
-
window.addEventListener("mouseup", up);
|
|
10139
|
-
};
|
|
10140
|
-
const getHandle = useCallback9(
|
|
10141
|
-
() => tab.terminalRef?.current ?? null,
|
|
10142
|
-
[tab.terminalRef]
|
|
10143
|
-
);
|
|
10144
|
-
const sshHost = useMemo10(
|
|
10145
|
-
() => tab.host ? hostToSSHHost(tab.host) : void 0,
|
|
10146
|
-
[tab.host]
|
|
10147
|
-
);
|
|
10148
|
-
const showEdge = defs.filter((def) => defaults3[def.id]?.edgeButton !== false);
|
|
10149
|
-
const vertical = side === "bottom";
|
|
10150
|
-
const clamped = vertical ? Math.min(baseSize, 2e3) : baseSize;
|
|
10151
|
-
const paneStyle = isMobile ? { height: "55%" } : vertical ? { height: clamped } : { width: clamped };
|
|
10152
|
-
const SideIcon = sideIcon(side);
|
|
10153
|
-
return /* @__PURE__ */ jsxs6("div", { className: "flex h-full w-full min-h-0 min-w-0", children: [
|
|
10154
|
-
defs.map(
|
|
10155
|
-
(def) => def.Defaults ? /* @__PURE__ */ jsx13(DefaultsReader, { def, onValue: onDefaults }, def.id) : null
|
|
10156
|
-
),
|
|
10157
|
-
/* @__PURE__ */ jsxs6(
|
|
10158
|
-
"div",
|
|
10159
|
-
{
|
|
10160
|
-
ref: rootRef,
|
|
10161
|
-
className: cn(
|
|
10162
|
-
"relative flex flex-1 min-h-0 min-w-0",
|
|
10163
|
-
vertical ? "flex-col" : side === "left" ? "flex-row-reverse" : "flex-row"
|
|
10164
|
-
),
|
|
10165
|
-
children: [
|
|
10166
|
-
/* @__PURE__ */ jsx13("div", { className: "relative flex-1 min-h-0 min-w-0", children }),
|
|
10167
|
-
defs.map((def) => {
|
|
10168
|
-
if (!mounted.has(def.id)) return null;
|
|
10169
|
-
const open = active?.id === def.id;
|
|
10170
|
-
const Component = def.component;
|
|
10171
|
-
const Icon = def.icon;
|
|
10172
|
-
return /* @__PURE__ */ jsxs6(
|
|
10173
|
-
"div",
|
|
10174
|
-
{
|
|
10175
|
-
className: cn(
|
|
10176
|
-
"relative flex-shrink-0 flex-col min-h-0 min-w-0 bg-background border-border",
|
|
10177
|
-
open ? "flex" : "hidden",
|
|
10178
|
-
vertical ? "border-t" : side === "left" ? "border-r" : "border-l",
|
|
10179
|
-
isMobile && "absolute inset-x-0 bottom-0 z-20 shadow-lg"
|
|
10180
|
-
),
|
|
10181
|
-
style: paneStyle,
|
|
10182
|
-
children: [
|
|
10183
|
-
!isMobile && /* @__PURE__ */ jsx13(
|
|
10184
|
-
"div",
|
|
10185
|
-
{
|
|
10186
|
-
role: "separator",
|
|
10187
|
-
"aria-label": t("companion.resize"),
|
|
10188
|
-
onMouseDown: startResize,
|
|
10189
|
-
className: cn(
|
|
10190
|
-
"absolute z-10",
|
|
10191
|
-
vertical ? "inset-x-0 -top-1 h-2 cursor-row-resize" : side === "left" ? "inset-y-0 -right-1 w-2 cursor-col-resize" : "inset-y-0 -left-1 w-2 cursor-col-resize",
|
|
10192
|
-
dragging && "bg-primary/30"
|
|
10193
|
-
)
|
|
10194
|
-
}
|
|
10195
|
-
),
|
|
10196
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5 h-8 px-2 border-b border-border flex-shrink-0", children: [
|
|
10197
|
-
Icon && /* @__PURE__ */ jsx13(Icon, { className: "size-3.5 text-muted-foreground" }),
|
|
10198
|
-
/* @__PURE__ */ jsx13("span", { className: "text-xs font-medium truncate flex-1", children: def.titleKey ? t(def.titleKey) : def.id }),
|
|
10199
|
-
!isMobile && /* @__PURE__ */ jsx13(
|
|
10200
|
-
"button",
|
|
10201
|
-
{
|
|
10202
|
-
type: "button",
|
|
10203
|
-
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10204
|
-
title: t("companion.moveSide"),
|
|
10205
|
-
onClick: () => setSide(
|
|
10206
|
-
side === "right" ? "bottom" : side === "bottom" ? "left" : "right"
|
|
10207
|
-
),
|
|
10208
|
-
children: /* @__PURE__ */ jsx13(SideIcon, { className: "size-3.5" })
|
|
10209
|
-
}
|
|
10210
|
-
),
|
|
10211
|
-
/* @__PURE__ */ jsx13(
|
|
10212
|
-
"button",
|
|
10213
|
-
{
|
|
10214
|
-
type: "button",
|
|
10215
|
-
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10216
|
-
title: t("companion.close"),
|
|
10217
|
-
onClick: close,
|
|
10218
|
-
children: /* @__PURE__ */ jsx13(X, { className: "size-3.5" })
|
|
10219
|
-
}
|
|
10220
|
-
)
|
|
10221
|
-
] }),
|
|
10222
|
-
/* @__PURE__ */ jsx13("div", { className: "flex-1 min-h-0 min-w-0 overflow-hidden", children: /* @__PURE__ */ jsx13(
|
|
10223
|
-
Component,
|
|
10224
|
-
{
|
|
10225
|
-
tab,
|
|
10226
|
-
host: tab.host,
|
|
10227
|
-
sshHost,
|
|
10228
|
-
getHandle,
|
|
10229
|
-
side,
|
|
10230
|
-
isVisible: isVisible && open,
|
|
10231
|
-
close,
|
|
10232
|
-
setSide
|
|
10233
|
-
}
|
|
10234
|
-
) })
|
|
10235
|
-
]
|
|
10236
|
-
},
|
|
10237
|
-
def.id
|
|
10238
|
-
);
|
|
10239
|
-
})
|
|
10240
|
-
]
|
|
10241
|
-
}
|
|
10242
|
-
),
|
|
10243
|
-
showEdge.length > 0 && !isMobile && /* @__PURE__ */ jsx13("div", { className: "flex flex-col flex-shrink-0 w-6 items-center gap-1 pt-1 border-l border-border bg-background", children: showEdge.map((def) => {
|
|
10244
|
-
const Icon = def.icon ?? PanelRight;
|
|
10245
|
-
const open = active?.id === def.id;
|
|
10246
|
-
return /* @__PURE__ */ jsx13(
|
|
10247
|
-
"button",
|
|
10248
|
-
{
|
|
10249
|
-
type: "button",
|
|
10250
|
-
title: def.titleKey ? t(def.titleKey) : def.id,
|
|
10251
|
-
"aria-pressed": open,
|
|
10252
|
-
onClick: () => patchCompanionState(key, {
|
|
10253
|
-
seen: true,
|
|
10254
|
-
openId: open ? null : def.id
|
|
10255
|
-
}),
|
|
10256
|
-
className: cn(
|
|
10257
|
-
"p-1 text-muted-foreground hover:text-foreground",
|
|
10258
|
-
open && "text-foreground bg-accent"
|
|
10259
|
-
),
|
|
10260
|
-
children: /* @__PURE__ */ jsx13(Icon, { className: "size-3.5" })
|
|
10261
|
-
},
|
|
10262
|
-
def.id
|
|
10263
|
-
);
|
|
10264
|
-
}) })
|
|
10265
|
-
] });
|
|
10266
|
-
}
|
|
10267
|
-
|
|
10268
|
-
// src/ui/shell/tabUtils.tsx
|
|
10269
|
-
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
10270
|
-
var PluginsTab = lazy(
|
|
10271
|
-
() => import("./PluginsTab-HQGSDSHS.js").then((m) => ({ default: m.PluginsTab }))
|
|
10272
|
-
);
|
|
10273
|
-
function preloadTabSurface(type) {
|
|
10274
|
-
const loader = getTabType(type)?.preload;
|
|
10275
|
-
if (loader) runAdaptiveBackgroundTask("module", `tab:${type}`, loader);
|
|
10276
|
-
}
|
|
10277
|
-
function markTabSurfaceUsed(type) {
|
|
10278
|
-
markAdaptiveResourceUsed("module", `tab:${type}`);
|
|
10279
|
-
}
|
|
10280
|
-
function EmptyState({
|
|
10281
|
-
icon: Icon,
|
|
10282
|
-
messageKey
|
|
10283
|
-
}) {
|
|
10284
|
-
const { t } = useTranslation9();
|
|
10285
|
-
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center flex-1 gap-3 p-6 text-center", children: [
|
|
10286
|
-
/* @__PURE__ */ jsx14("div", { className: "size-10 rounded-full bg-muted/40 flex items-center justify-center", children: /* @__PURE__ */ jsx14(Icon, { className: "size-5 text-muted-foreground/30" }) }),
|
|
10287
|
-
/* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-muted-foreground/60", children: t(messageKey) })
|
|
10288
|
-
] });
|
|
10289
|
-
}
|
|
10290
|
-
function TabChunkFallback() {
|
|
10291
|
-
return /* @__PURE__ */ jsx14("div", { className: "flex h-full w-full items-center justify-center bg-background", children: /* @__PURE__ */ jsx14("div", { className: "size-5 rounded-full border-2 border-muted-foreground/30 border-t-muted-foreground/70 animate-spin" }) });
|
|
10292
|
-
}
|
|
10293
|
-
function withTabSuspense(node) {
|
|
10294
|
-
return /* @__PURE__ */ jsx14(Suspense, { fallback: /* @__PURE__ */ jsx14(TabChunkFallback, {}), children: node });
|
|
10295
|
-
}
|
|
10296
|
-
function PanelTabFrame({ children }) {
|
|
10297
|
-
return /* @__PURE__ */ jsx14("div", { className: "flex h-full w-full justify-center overflow-y-auto bg-background", children: /* @__PURE__ */ jsx14("div", { className: "flex flex-col flex-1 min-h-0 w-full max-w-5xl", children }) });
|
|
10298
|
-
}
|
|
10299
|
-
function tabIcon(type) {
|
|
10300
|
-
switch (type) {
|
|
10301
|
-
case "user-profile":
|
|
10302
|
-
case "admin-settings":
|
|
10303
|
-
return /* @__PURE__ */ jsx14(Settings, { className: "size-3.5" });
|
|
10304
|
-
case "split-screen":
|
|
10305
|
-
return /* @__PURE__ */ jsx14(LayoutPanelLeft, { className: "size-3.5" });
|
|
10306
|
-
case "plugins":
|
|
10307
|
-
return /* @__PURE__ */ jsx14(Puzzle, { className: "size-3.5" });
|
|
10308
|
-
default: {
|
|
10309
|
-
const Icon = getTabType(type)?.icon;
|
|
10310
|
-
return Icon ? /* @__PURE__ */ jsx14(Icon, { className: "size-3.5" }) : null;
|
|
10311
|
-
}
|
|
10312
|
-
}
|
|
10313
|
-
}
|
|
10314
|
-
var RegisteredTab = memo2(function RegisteredTab2({
|
|
10315
|
-
def,
|
|
10316
|
-
tab,
|
|
10317
|
-
isVisible,
|
|
10318
|
-
isFocusedPane,
|
|
10319
|
-
inSplit,
|
|
10320
|
-
shell: shell2
|
|
10321
|
-
}) {
|
|
10322
|
-
const { host, label } = tab;
|
|
10323
|
-
if (def.requiresHost && !host) {
|
|
10324
|
-
return /* @__PURE__ */ jsx14(
|
|
10325
|
-
EmptyState,
|
|
10326
|
-
{
|
|
10327
|
-
icon: Server,
|
|
10328
|
-
messageKey: def.noHostMessageKey ?? "hosts.noHostSelected"
|
|
10329
|
-
}
|
|
10330
|
-
);
|
|
10331
|
-
}
|
|
10332
|
-
const Component = def.component;
|
|
10333
|
-
const content = /* @__PURE__ */ jsx14(
|
|
10334
|
-
Component,
|
|
10335
|
-
{
|
|
10336
|
-
tab,
|
|
10337
|
-
host,
|
|
10338
|
-
sshHost: host ? hostToSSHHost(host) : void 0,
|
|
10339
|
-
label,
|
|
10340
|
-
isVisible,
|
|
10341
|
-
isFocusedPane,
|
|
10342
|
-
inSplit,
|
|
10343
|
-
handleRef: trackTabHandle(
|
|
10344
|
-
tab.terminalRef
|
|
10345
|
-
),
|
|
10346
|
-
shell: shell2
|
|
10347
|
-
}
|
|
10348
|
-
);
|
|
10349
|
-
return withTabSuspense(
|
|
10350
|
-
/* @__PURE__ */ jsx14(CompanionFrame, { tab, isVisible, children: def.panelFrame ? /* @__PURE__ */ jsx14(PanelTabFrame, { children: content }) : content })
|
|
10351
|
-
);
|
|
10352
|
-
});
|
|
10353
|
-
var PanelAsTab = memo2(function PanelAsTab2({
|
|
10354
|
-
panel,
|
|
10355
|
-
isVisible,
|
|
10356
|
-
targetTab,
|
|
10357
|
-
shell: shell2
|
|
10358
|
-
}) {
|
|
10359
|
-
const Panel = panel.component;
|
|
10360
|
-
return withTabSuspense(
|
|
10361
|
-
/* @__PURE__ */ jsx14(PanelTabFrame, { children: /* @__PURE__ */ jsx14(
|
|
10362
|
-
Panel,
|
|
10363
|
-
{
|
|
10364
|
-
targetTab,
|
|
10365
|
-
active: isVisible,
|
|
10366
|
-
shell: shell2,
|
|
10367
|
-
setEditing: noop,
|
|
10368
|
-
placement: "tab"
|
|
10369
|
-
}
|
|
10370
|
-
) })
|
|
10371
|
-
);
|
|
10372
|
-
});
|
|
10373
|
-
function noop() {
|
|
10374
|
-
}
|
|
10375
|
-
function renderTabContent(tab, context) {
|
|
10376
|
-
const {
|
|
10377
|
-
shell: shell2,
|
|
10378
|
-
isVisible = true,
|
|
10379
|
-
isFocusedPane = true,
|
|
10380
|
-
inSplit = false
|
|
10381
|
-
} = context;
|
|
10382
|
-
switch (tab.type) {
|
|
10383
|
-
case "split-screen":
|
|
10384
|
-
return null;
|
|
10385
|
-
case "plugins":
|
|
10386
|
-
return withTabSuspense(/* @__PURE__ */ jsx14(PluginsTab, {}));
|
|
10387
|
-
case "user-profile":
|
|
10388
|
-
case "admin-settings":
|
|
10389
|
-
return null;
|
|
10390
|
-
default: {
|
|
10391
|
-
const def = getTabType(tab.type);
|
|
10392
|
-
if (!def && tab.type === "dashboard") return null;
|
|
10393
|
-
if (!def) {
|
|
10394
|
-
const panel = getPanel(tab.type);
|
|
10395
|
-
if (panel) {
|
|
10396
|
-
return /* @__PURE__ */ jsx14(
|
|
10397
|
-
PanelAsTab,
|
|
10398
|
-
{
|
|
10399
|
-
panel,
|
|
10400
|
-
isVisible,
|
|
10401
|
-
targetTab: context.panelTargetTab,
|
|
10402
|
-
shell: shell2
|
|
10403
|
-
}
|
|
10404
|
-
);
|
|
10405
|
-
}
|
|
10406
|
-
return /* @__PURE__ */ jsx14(PluginViewPlaceholder, { kind: "tab", viewId: tab.type });
|
|
10407
|
-
}
|
|
10408
|
-
return /* @__PURE__ */ jsx14(
|
|
10409
|
-
RegisteredTab,
|
|
10410
|
-
{
|
|
10411
|
-
def,
|
|
10412
|
-
tab,
|
|
10413
|
-
isVisible,
|
|
10414
|
-
isFocusedPane,
|
|
10415
|
-
inSplit,
|
|
10416
|
-
shell: shell2
|
|
10417
|
-
}
|
|
10418
|
-
);
|
|
10419
|
-
}
|
|
10420
|
-
}
|
|
10421
|
-
}
|
|
10422
|
-
|
|
10423
|
-
// src/ui/lib/local-adaptive-preferences.ts
|
|
10424
|
-
init_define_import_meta_env();
|
|
10425
|
-
var LOCAL_ADAPTIVE_PREFERENCES_KEY = LOCAL_ADAPTIVE_ENGINE_KEY;
|
|
10426
|
-
function recordLocalPreference(scope, action, now = Date.now()) {
|
|
10427
|
-
recordLocalAdaptiveChoice(scope, action, now);
|
|
10428
|
-
}
|
|
10429
|
-
function getLocalPreference(scope, candidates, fallback, now = Date.now()) {
|
|
10430
|
-
return chooseLocalAdaptiveAction({
|
|
10431
|
-
scope,
|
|
10432
|
-
candidates,
|
|
10433
|
-
fallback,
|
|
10434
|
-
now
|
|
10435
|
-
}).action;
|
|
10436
|
-
}
|
|
10437
|
-
function clearLocalAdaptivePreferences() {
|
|
10438
|
-
clearLocalAdaptiveEngine();
|
|
10439
|
-
}
|
|
10440
|
-
var hostActionScope = (hostId) => `host-action:${hostId}`;
|
|
10441
|
-
function recordHostActionPreference(hostId, action) {
|
|
10442
|
-
recordLocalPreference(hostActionScope(hostId), action);
|
|
10443
|
-
}
|
|
10444
|
-
function getPreferredHostAction(hostId, candidates, fallback) {
|
|
10445
|
-
return getLocalPreference(hostActionScope(hostId), candidates, fallback);
|
|
10446
|
-
}
|
|
10447
|
-
|
|
10448
9008
|
export {
|
|
10449
|
-
Checkbox2 as Checkbox,
|
|
10450
|
-
PasswordInput,
|
|
10451
|
-
Textarea,
|
|
10452
9009
|
rem,
|
|
10453
9010
|
remScale,
|
|
10454
9011
|
useIsMobile,
|
|
@@ -10487,6 +9044,14 @@ export {
|
|
|
10487
9044
|
isCoreRailView,
|
|
10488
9045
|
railItemLabel,
|
|
10489
9046
|
resetRegisteredRailItems,
|
|
9047
|
+
useCompanionDefs,
|
|
9048
|
+
useCompanionLayoutDefs,
|
|
9049
|
+
resolveCompanionLayout,
|
|
9050
|
+
companionApplies,
|
|
9051
|
+
arrangeCompanions,
|
|
9052
|
+
companionKey,
|
|
9053
|
+
patchCompanionState,
|
|
9054
|
+
useCompanionState,
|
|
10490
9055
|
registerHostEditorSection,
|
|
10491
9056
|
unregisterHostEditorSection,
|
|
10492
9057
|
getHostEditorSection,
|
|
@@ -10540,8 +9105,10 @@ export {
|
|
|
10540
9105
|
listExtensions,
|
|
10541
9106
|
getSettingsComponent,
|
|
10542
9107
|
listSettingsComponents,
|
|
9108
|
+
useSettingsComponents,
|
|
10543
9109
|
registerAction,
|
|
10544
9110
|
listActions,
|
|
9111
|
+
invokeAction,
|
|
10545
9112
|
declareActionSlot,
|
|
10546
9113
|
registerSlotContribution,
|
|
10547
9114
|
getSlotContributions,
|
|
@@ -10626,25 +9193,5 @@ export {
|
|
|
10626
9193
|
useLayouts,
|
|
10627
9194
|
layoutLabel,
|
|
10628
9195
|
createPluginApp,
|
|
10629
|
-
|
|
10630
|
-
SettingsFieldRow,
|
|
10631
|
-
usePluginHostSections,
|
|
10632
|
-
HostPluginSections,
|
|
10633
|
-
HostFeatureFields,
|
|
10634
|
-
ActionSlot,
|
|
10635
|
-
ComponentSlot,
|
|
10636
|
-
trackTabHandle,
|
|
10637
|
-
useTabHandlesVersion,
|
|
10638
|
-
PluginViewPlaceholder,
|
|
10639
|
-
markAdaptiveResourceUsed,
|
|
10640
|
-
getAdaptiveResourceBudget,
|
|
10641
|
-
runAdaptiveBackgroundTask,
|
|
10642
|
-
preloadTabSurface,
|
|
10643
|
-
markTabSurfaceUsed,
|
|
10644
|
-
tabIcon,
|
|
10645
|
-
renderTabContent,
|
|
10646
|
-
LOCAL_ADAPTIVE_PREFERENCES_KEY,
|
|
10647
|
-
clearLocalAdaptivePreferences,
|
|
10648
|
-
recordHostActionPreference,
|
|
10649
|
-
getPreferredHostAction
|
|
9196
|
+
hostToSSHHost
|
|
10650
9197
|
};
|