@termix-ssh/plugin-sdk 1.0.20 → 1.0.22
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 +29 -0
- package/PLUGIN-GUIDE.md +66 -4
- package/cli/commands/build.mjs +55 -36
- package/cli/commands/validate.mjs +4 -0
- package/dist/backend.d.ts +32 -7
- package/dist/frontend.d.ts +7 -0
- package/dist/host/{PluginsTab-ZSMTJ5C5.js → PluginsTab-CM2B33BD.js} +26 -16
- package/dist/host/chunk-7J4QNGFM.js +345 -0
- package/dist/host/{chunk-J3ZQPBDK.js → chunk-HQ6NNFSX.js} +115 -1575
- package/dist/host/chunk-I5F2PSMR.js +1526 -0
- package/dist/host/{chunk-2MU6WNSX.js → chunk-JRV2HIDK.js} +1 -1
- package/dist/host/{chunk-7LEJ3HYF.js → chunk-P26QKKU5.js} +41 -10
- package/dist/host/{chunk-CITUENSU.js → chunk-ROB2SH5Q.js} +77 -49
- package/dist/host/chunk-TK3Y437H.js +53 -0
- package/dist/host/{chunk-EYONBBRJ.js → chunk-VKNGNEF3.js} +34650 -34968
- 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-OUF3POT7.js → linked-server-J5G457OA.js} +1 -1
- package/dist/host/{rbac-api-LZVENREG.js → rbac-api-PY22W5UY.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/look-api.d.ts +2 -0
- package/dist/host/types/src/ui/api/plugins-api.d.ts +3 -2
- 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/app-return.d.ts +13 -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/plugin-model.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 +418 -388
- package/dist/host/{use-permissions-BYCDS5PD.js → use-permissions-EWRI3WLT.js} +1 -1
- package/dist/host-commands.d.ts +9 -6
- package/dist/host-commands.js +38 -11
- package/dist/host-scripts/docker.d.ts +137 -0
- package/dist/host-scripts/docker.js +345 -0
- package/dist/host-scripts/index.d.ts +15 -0
- package/dist/host-scripts/index.js +15 -0
- package/dist/host-scripts/journal.d.ts +45 -0
- package/dist/host-scripts/journal.js +194 -0
- package/dist/host-scripts/metrics.d.ts +134 -0
- package/dist/host-scripts/metrics.js +320 -0
- package/dist/host-scripts/openrc.d.ts +6 -0
- package/dist/host-scripts/openrc.js +90 -0
- package/dist/host-scripts/shell.d.ts +43 -0
- package/dist/host-scripts/shell.js +95 -0
- package/dist/host-scripts/systemd.d.ts +73 -0
- package/dist/host-scripts/systemd.js +320 -0
- package/dist/host-scripts/text.d.ts +23 -0
- package/dist/host-scripts/text.js +111 -0
- package/dist/manifest.d.ts +28 -1
- package/dist/manifest.js +108 -1
- package/package.json +9 -1
- package/schema/manifest.schema.json +42 -0
|
@@ -3,65 +3,33 @@ import {
|
|
|
3
3
|
hasPermission,
|
|
4
4
|
resetPermissionsCache,
|
|
5
5
|
usePermissions
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JRV2HIDK.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-VKNGNEF3.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-P26QKKU5.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;
|
|
@@ -1144,6 +1031,10 @@ var en_default = {
|
|
|
1144
1031
|
ready: "Termix {{version}} is ready to install",
|
|
1145
1032
|
readyHint: "It installs the next time Termix restarts."
|
|
1146
1033
|
},
|
|
1034
|
+
safeMode: {
|
|
1035
|
+
title: "Safe mode",
|
|
1036
|
+
description: "Only layout and theme plugins are running. Restart the server without TERMIX_SAFE_MODE to turn the rest back on."
|
|
1037
|
+
},
|
|
1147
1038
|
companion: {
|
|
1148
1039
|
close: "Close panel",
|
|
1149
1040
|
moveSide: "Move panel",
|
|
@@ -1495,6 +1386,8 @@ var en_default = {
|
|
|
1495
1386
|
closeOnOpenDesc: "Close the sidebar after you open a host from it",
|
|
1496
1387
|
showFolderPaths: "Show folder paths",
|
|
1497
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",
|
|
1498
1391
|
rowDetailsTitle: "Row details",
|
|
1499
1392
|
rowDetailsDesc: "Choose what shows on each host.",
|
|
1500
1393
|
showAddress: "Address",
|
|
@@ -1680,6 +1573,8 @@ var en_default = {
|
|
|
1680
1573
|
sharedBadge: "Shared",
|
|
1681
1574
|
sharedBadgeTooltip: "Shared by {{owner}} ({{level}} access)",
|
|
1682
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.",
|
|
1683
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.",
|
|
1684
1579
|
ownerOnlyControl: "Only the host owner can change this",
|
|
1685
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.",
|
|
@@ -2220,7 +2115,8 @@ var en_default = {
|
|
|
2220
2115
|
disabled: "Disabled",
|
|
2221
2116
|
failed: "Stopped unexpectedly",
|
|
2222
2117
|
blocked: "Waiting on another plugin",
|
|
2223
|
-
server: "Runs on your server"
|
|
2118
|
+
server: "Runs on your server",
|
|
2119
|
+
safeMode: "Off in safe mode"
|
|
2224
2120
|
},
|
|
2225
2121
|
groups: {
|
|
2226
2122
|
running: "Running",
|
|
@@ -2857,7 +2753,7 @@ function resetRegisteredRailItems() {
|
|
|
2857
2753
|
|
|
2858
2754
|
// src/ui/sidebar/HostManagerTabs.tsx
|
|
2859
2755
|
init_define_import_meta_env();
|
|
2860
|
-
import { jsx
|
|
2756
|
+
import { jsx } from "react/jsx-runtime";
|
|
2861
2757
|
var sections = createRegistry(byOrderThenId);
|
|
2862
2758
|
var registerHostEditorSection = sections.register;
|
|
2863
2759
|
var unregisterHostEditorSection = sections.unregister;
|
|
@@ -2881,7 +2777,7 @@ function mergeByOrder(core, group, t, protocols2, defaultsMode = false) {
|
|
|
2881
2777
|
return {
|
|
2882
2778
|
id: section.id,
|
|
2883
2779
|
label: t(section.labelKey, { defaultValue: section.label }),
|
|
2884
|
-
icon: Icon ? /* @__PURE__ */
|
|
2780
|
+
icon: Icon ? /* @__PURE__ */ jsx(Icon, { className: "size-3" }) : null,
|
|
2885
2781
|
order: section.order ?? 1e3
|
|
2886
2782
|
};
|
|
2887
2783
|
});
|
|
@@ -2893,13 +2789,13 @@ function makeHostTabs(t, protocols2, defaultsMode = false) {
|
|
|
2893
2789
|
{
|
|
2894
2790
|
id: "general",
|
|
2895
2791
|
label: t("hosts.tabGeneral"),
|
|
2896
|
-
icon: /* @__PURE__ */
|
|
2792
|
+
icon: /* @__PURE__ */ jsx(Settings, { className: "size-3" }),
|
|
2897
2793
|
order: 0
|
|
2898
2794
|
},
|
|
2899
2795
|
{
|
|
2900
2796
|
id: "ssh",
|
|
2901
2797
|
label: t("hosts.tabSsh"),
|
|
2902
|
-
icon: /* @__PURE__ */
|
|
2798
|
+
icon: /* @__PURE__ */ jsx(Terminal, { className: "size-3" }),
|
|
2903
2799
|
order: 10
|
|
2904
2800
|
}
|
|
2905
2801
|
],
|
|
@@ -2915,7 +2811,7 @@ function makeHostSshSubTabs(t, protocols2, defaultsMode = false) {
|
|
|
2915
2811
|
{
|
|
2916
2812
|
id: "ssh",
|
|
2917
2813
|
label: t("hosts.tabGeneral"),
|
|
2918
|
-
icon: /* @__PURE__ */
|
|
2814
|
+
icon: /* @__PURE__ */ jsx(Settings, { className: "size-3" }),
|
|
2919
2815
|
order: 0
|
|
2920
2816
|
}
|
|
2921
2817
|
],
|
|
@@ -3389,7 +3285,7 @@ async function pluginWsUrl(pluginId, path2, options = {}) {
|
|
|
3389
3285
|
}
|
|
3390
3286
|
const token = await fetchSocketTicket() ?? localStorage.getItem("jwt");
|
|
3391
3287
|
const protocols2 = websocketAuthProtocols(token);
|
|
3392
|
-
const devProxy =
|
|
3288
|
+
const devProxy = false;
|
|
3393
3289
|
const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
3394
3290
|
if (devProxy) {
|
|
3395
3291
|
return {
|
|
@@ -3465,7 +3361,7 @@ function sectionPosition(section, order2 = 0, position) {
|
|
|
3465
3361
|
|
|
3466
3362
|
// src/ui/hooks/use-status-color-scheme.ts
|
|
3467
3363
|
init_define_import_meta_env();
|
|
3468
|
-
import { useState as
|
|
3364
|
+
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
3469
3365
|
var PREFS_KEY = "hostSidebarPreferences";
|
|
3470
3366
|
var PREFS_EVENT = "hostSidebarPreferencesChanged";
|
|
3471
3367
|
function readStatusColorScheme() {
|
|
@@ -3479,7 +3375,7 @@ function readStatusColorScheme() {
|
|
|
3479
3375
|
}
|
|
3480
3376
|
}
|
|
3481
3377
|
function useStatusColorScheme() {
|
|
3482
|
-
const [scheme, setScheme] =
|
|
3378
|
+
const [scheme, setScheme] = useState2(
|
|
3483
3379
|
readStatusColorScheme
|
|
3484
3380
|
);
|
|
3485
3381
|
useEffect2(() => {
|
|
@@ -3519,10 +3415,6 @@ function getStatusClasses(status, scheme, variant, loading = false) {
|
|
|
3519
3415
|
return online ? "border-accent-brand/40 text-accent-brand bg-accent-brand/10" : "border-border/50 text-muted-foreground/60 bg-muted/30";
|
|
3520
3416
|
}
|
|
3521
3417
|
|
|
3522
|
-
// src/ui/components/theme-provider.tsx
|
|
3523
|
-
init_define_import_meta_env();
|
|
3524
|
-
import { createContext, useContext, useEffect as useEffect3, useState as useState4 } from "react";
|
|
3525
|
-
|
|
3526
3418
|
// src/ui/look/theme-registry.ts
|
|
3527
3419
|
init_define_import_meta_env();
|
|
3528
3420
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -3606,6 +3498,10 @@ function arePluginThemesKnown() {
|
|
|
3606
3498
|
return pluginThemesKnown;
|
|
3607
3499
|
}
|
|
3608
3500
|
|
|
3501
|
+
// src/ui/components/theme-provider.tsx
|
|
3502
|
+
init_define_import_meta_env();
|
|
3503
|
+
import { createContext, useContext, useEffect as useEffect3, useState as useState3 } from "react";
|
|
3504
|
+
|
|
3609
3505
|
// src/ui/look/theme-css.ts
|
|
3610
3506
|
init_define_import_meta_env();
|
|
3611
3507
|
var LINK_ID = "termix-theme-css";
|
|
@@ -3656,7 +3552,7 @@ function applyThemeCss(id, theme) {
|
|
|
3656
3552
|
}
|
|
3657
3553
|
|
|
3658
3554
|
// src/ui/components/theme-provider.tsx
|
|
3659
|
-
import { jsx as
|
|
3555
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
3660
3556
|
var initialState = {
|
|
3661
3557
|
theme: "dark",
|
|
3662
3558
|
setTheme: () => null,
|
|
@@ -3670,10 +3566,10 @@ function ThemeProvider({
|
|
|
3670
3566
|
storageKey = "vite-ui-theme",
|
|
3671
3567
|
...props
|
|
3672
3568
|
}) {
|
|
3673
|
-
const [theme, setTheme] =
|
|
3569
|
+
const [theme, setTheme] = useState3(
|
|
3674
3570
|
() => localStorage.getItem(storageKey) || defaultTheme
|
|
3675
3571
|
);
|
|
3676
|
-
const [previewTheme, setPreviewTheme] =
|
|
3572
|
+
const [previewTheme, setPreviewTheme] = useState3(null);
|
|
3677
3573
|
const themes = useThemes();
|
|
3678
3574
|
const shownTheme = effectiveThemeId(theme);
|
|
3679
3575
|
const activeTheme = previewTheme ?? shownTheme;
|
|
@@ -3696,7 +3592,7 @@ function ThemeProvider({
|
|
|
3696
3592
|
setPreviewTheme(preview);
|
|
3697
3593
|
}
|
|
3698
3594
|
};
|
|
3699
|
-
return /* @__PURE__ */
|
|
3595
|
+
return /* @__PURE__ */ jsx2(ThemeProviderContext.Provider, { ...props, value, children });
|
|
3700
3596
|
}
|
|
3701
3597
|
var useTheme = () => {
|
|
3702
3598
|
const context = useContext(ThemeProviderContext);
|
|
@@ -3707,7 +3603,7 @@ var useTheme = () => {
|
|
|
3707
3603
|
|
|
3708
3604
|
// src/ui/hooks/useSshAuthProviders.ts
|
|
3709
3605
|
init_define_import_meta_env();
|
|
3710
|
-
import { useEffect as useEffect4, useMemo as useMemo2, useState as
|
|
3606
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
|
|
3711
3607
|
var BUILTIN_TYPES = ["password", "key", "credential", "agent", "none"];
|
|
3712
3608
|
function builtinSummary(type) {
|
|
3713
3609
|
return {
|
|
@@ -3725,7 +3621,7 @@ function builtinSummary(type) {
|
|
|
3725
3621
|
var cache = null;
|
|
3726
3622
|
function useSshAuthProviders() {
|
|
3727
3623
|
const editors = useSshAuthEditors();
|
|
3728
|
-
const [summaries, setSummaries] =
|
|
3624
|
+
const [summaries, setSummaries] = useState4(
|
|
3729
3625
|
null
|
|
3730
3626
|
);
|
|
3731
3627
|
useEffect4(() => {
|
|
@@ -3807,14 +3703,14 @@ import {
|
|
|
3807
3703
|
useContext as useContext2,
|
|
3808
3704
|
useEffect as useEffect5,
|
|
3809
3705
|
useMemo as useMemo4,
|
|
3810
|
-
useState as
|
|
3706
|
+
useState as useState5
|
|
3811
3707
|
} from "react";
|
|
3812
3708
|
|
|
3813
3709
|
// src/ui/contexts/branding-document.ts
|
|
3814
3710
|
init_define_import_meta_env();
|
|
3815
3711
|
|
|
3816
3712
|
// src/ui/contexts/BrandingContext.tsx
|
|
3817
|
-
import { jsx as
|
|
3713
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
3818
3714
|
var DEFAULT_APP_NAME = "Termix";
|
|
3819
3715
|
var BrandingContext = createContext2({
|
|
3820
3716
|
ready: false,
|
|
@@ -5205,7 +5101,7 @@ import {
|
|
|
5205
5101
|
useLayoutEffect as useLayoutEffect2,
|
|
5206
5102
|
useMemo as useMemo5,
|
|
5207
5103
|
useRef as useRef6,
|
|
5208
|
-
useState as
|
|
5104
|
+
useState as useState11
|
|
5209
5105
|
} from "react";
|
|
5210
5106
|
|
|
5211
5107
|
// src/ui/shell/stage/tab-stage-store.ts
|
|
@@ -5213,14 +5109,14 @@ init_define_import_meta_env();
|
|
|
5213
5109
|
function createTabStageStore() {
|
|
5214
5110
|
const nodes = /* @__PURE__ */ new Map();
|
|
5215
5111
|
const paneEls = /* @__PURE__ */ new Map();
|
|
5216
|
-
const
|
|
5112
|
+
const listeners8 = /* @__PURE__ */ new Set();
|
|
5217
5113
|
let normalView = null;
|
|
5218
|
-
let
|
|
5114
|
+
let version3 = 0;
|
|
5219
5115
|
let order2 = [];
|
|
5220
5116
|
let lastAnimatedTabId = null;
|
|
5221
5117
|
const bump = () => {
|
|
5222
|
-
|
|
5223
|
-
for (const listener of
|
|
5118
|
+
version3 += 1;
|
|
5119
|
+
for (const listener of listeners8) listener();
|
|
5224
5120
|
};
|
|
5225
5121
|
function getNode(tabId, ownBackground) {
|
|
5226
5122
|
let el = nodes.get(tabId);
|
|
@@ -5322,18 +5218,18 @@ function createTabStageStore() {
|
|
|
5322
5218
|
setNormalView,
|
|
5323
5219
|
place,
|
|
5324
5220
|
subscribe: (listener) => {
|
|
5325
|
-
|
|
5221
|
+
listeners8.add(listener);
|
|
5326
5222
|
return () => {
|
|
5327
|
-
|
|
5223
|
+
listeners8.delete(listener);
|
|
5328
5224
|
};
|
|
5329
5225
|
},
|
|
5330
|
-
version: () =>
|
|
5226
|
+
version: () => version3
|
|
5331
5227
|
};
|
|
5332
5228
|
}
|
|
5333
5229
|
|
|
5334
5230
|
// src/ui/shell/controller/use-regions.ts
|
|
5335
5231
|
init_define_import_meta_env();
|
|
5336
|
-
import { useCallback as useCallback2, useEffect as useEffect6, useRef, useState as
|
|
5232
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useRef, useState as useState6 } from "react";
|
|
5337
5233
|
var MIN_WIDTH = 160;
|
|
5338
5234
|
var MAX_WIDTH = 480;
|
|
5339
5235
|
function clampWidth(width) {
|
|
@@ -5366,15 +5262,15 @@ function startDockDrag(e, startW, sign, setWidth, setDragging) {
|
|
|
5366
5262
|
}
|
|
5367
5263
|
var DOCK_DEFAULT_WIDTH = 291;
|
|
5368
5264
|
function useRegions(isMobile) {
|
|
5369
|
-
const [sidebarOpen, setSidebarOpen] =
|
|
5370
|
-
const [railView, setRailView] =
|
|
5371
|
-
const [sidebarWidth, setSidebarWidth] =
|
|
5265
|
+
const [sidebarOpen, setSidebarOpen] = useState6(true);
|
|
5266
|
+
const [railView, setRailView] = useState6("hosts");
|
|
5267
|
+
const [sidebarWidth, setSidebarWidth] = useState6(() => {
|
|
5372
5268
|
const saved = localStorage.getItem("termix_sidebarWidth");
|
|
5373
5269
|
return saved ? parseInt(saved, 10) : 291;
|
|
5374
5270
|
});
|
|
5375
|
-
const [sidebarDragging, setSidebarDragging] =
|
|
5376
|
-
const [panelEditing, setPanelEditing] =
|
|
5377
|
-
const [scopeEditing, setScopeEditing] =
|
|
5271
|
+
const [sidebarDragging, setSidebarDragging] = useState6(false);
|
|
5272
|
+
const [panelEditing, setPanelEditing] = useState6({});
|
|
5273
|
+
const [scopeEditing, setScopeEditing] = useState6({});
|
|
5378
5274
|
const editingSetters = useRef(
|
|
5379
5275
|
/* @__PURE__ */ new Map()
|
|
5380
5276
|
);
|
|
@@ -5400,15 +5296,15 @@ function useRegions(isMobile) {
|
|
|
5400
5296
|
);
|
|
5401
5297
|
return editingSetters.current.get(key);
|
|
5402
5298
|
}, []);
|
|
5403
|
-
const [rightRailView, setRightRailView] =
|
|
5299
|
+
const [rightRailView, setRightRailView] = useState6(() => {
|
|
5404
5300
|
const saved = localStorage.getItem("termix_rightRailView");
|
|
5405
5301
|
return saved && rightDockableIds().includes(saved) ? saved : null;
|
|
5406
5302
|
});
|
|
5407
|
-
const [rightSidebarWidth, setRightSidebarWidth] =
|
|
5303
|
+
const [rightSidebarWidth, setRightSidebarWidth] = useState6(() => {
|
|
5408
5304
|
const saved = localStorage.getItem("termix_rightSidebarWidth");
|
|
5409
5305
|
return saved ? parseInt(saved, 10) : 291;
|
|
5410
5306
|
});
|
|
5411
|
-
const [rightSidebarDragging, setRightSidebarDragging] =
|
|
5307
|
+
const [rightSidebarDragging, setRightSidebarDragging] = useState6(false);
|
|
5412
5308
|
const lastRightRailViewRef = useRef(
|
|
5413
5309
|
localStorage.getItem("termix_lastRightRailView")
|
|
5414
5310
|
);
|
|
@@ -5519,7 +5415,7 @@ function useRegions(isMobile) {
|
|
|
5519
5415
|
|
|
5520
5416
|
// src/ui/shell/controller/use-hosts.ts
|
|
5521
5417
|
init_define_import_meta_env();
|
|
5522
|
-
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef2, useState as
|
|
5418
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef2, useState as useState7 } from "react";
|
|
5523
5419
|
|
|
5524
5420
|
// src/ui/sidebar/build-host-tree.ts
|
|
5525
5421
|
init_define_import_meta_env();
|
|
@@ -5591,10 +5487,10 @@ function buildHostTree(hosts, folderMeta) {
|
|
|
5591
5487
|
|
|
5592
5488
|
// src/ui/shell/controller/use-hosts.ts
|
|
5593
5489
|
function useHostList() {
|
|
5594
|
-
const [tree, setTree] =
|
|
5595
|
-
const [loading, setLoading] =
|
|
5596
|
-
const [loaded, setLoaded] =
|
|
5597
|
-
const [list, setList] =
|
|
5490
|
+
const [tree, setTree] = useState7(null);
|
|
5491
|
+
const [loading, setLoading] = useState7(true);
|
|
5492
|
+
const [loaded, setLoaded] = useState7(false);
|
|
5493
|
+
const [list, setList] = useState7([]);
|
|
5598
5494
|
const listRef = useRef2(list);
|
|
5599
5495
|
listRef.current = list;
|
|
5600
5496
|
const reload = useCallback3(async () => {
|
|
@@ -5651,7 +5547,7 @@ import {
|
|
|
5651
5547
|
useCallback as useCallback4,
|
|
5652
5548
|
useEffect as useEffect8,
|
|
5653
5549
|
useRef as useRef3,
|
|
5654
|
-
useState as
|
|
5550
|
+
useState as useState8
|
|
5655
5551
|
} from "react";
|
|
5656
5552
|
import { toast } from "sonner";
|
|
5657
5553
|
import { useTranslation } from "react-i18next";
|
|
@@ -5703,10 +5599,10 @@ function useTabs({
|
|
|
5703
5599
|
}) {
|
|
5704
5600
|
const { t } = useTranslation();
|
|
5705
5601
|
const splitLabel = useSplitLabel();
|
|
5706
|
-
const [tabs, setTabs] =
|
|
5707
|
-
const [activeTabId, setActiveTabId] =
|
|
5708
|
-
const [tabsReady, setTabsReady] =
|
|
5709
|
-
const [backgroundTabRecords, setBackgroundTabRecords] =
|
|
5602
|
+
const [tabs, setTabs] = useState8([dashboardTab(t("nav.dashboard"))]);
|
|
5603
|
+
const [activeTabId, setActiveTabId] = useState8("dashboard");
|
|
5604
|
+
const [tabsReady, setTabsReady] = useState8(false);
|
|
5605
|
+
const [backgroundTabRecords, setBackgroundTabRecords] = useState8([]);
|
|
5710
5606
|
const paneLayoutRestoredRef = useRef3(false);
|
|
5711
5607
|
const splitTabsRestoredRef = useRef3(false);
|
|
5712
5608
|
const splitOpsRef = useRef3({
|
|
@@ -5795,14 +5691,14 @@ function useTabs({
|
|
|
5795
5691
|
if (!isSplitTab(active)) return activeTabId;
|
|
5796
5692
|
return findPane(active.split, active.split.focusedPaneId)?.tabId ?? "";
|
|
5797
5693
|
})();
|
|
5798
|
-
const [lastTerminalTabId, setLastTerminalTabId] =
|
|
5694
|
+
const [lastTerminalTabId, setLastTerminalTabId] = useState8(activeTabId);
|
|
5799
5695
|
useEffect8(() => {
|
|
5800
5696
|
const working = tabs.find((t2) => t2.id === workingTabId);
|
|
5801
5697
|
if (working && getTabType(working.type)?.commandTarget) {
|
|
5802
5698
|
setLastTerminalTabId(working.id);
|
|
5803
5699
|
}
|
|
5804
5700
|
}, [workingTabId, tabs]);
|
|
5805
|
-
const [showTabNumbers, setShowTabNumbers] =
|
|
5701
|
+
const [showTabNumbers, setShowTabNumbers] = useState8(
|
|
5806
5702
|
() => localStorage.getItem("showTabNumbers") === "true"
|
|
5807
5703
|
);
|
|
5808
5704
|
useEffect8(() => {
|
|
@@ -6356,7 +6252,7 @@ function useSplit({
|
|
|
6356
6252
|
tabsState,
|
|
6357
6253
|
isMobile,
|
|
6358
6254
|
paneEls,
|
|
6359
|
-
callbacks
|
|
6255
|
+
callbacks,
|
|
6360
6256
|
resizeAllTerminals
|
|
6361
6257
|
}) {
|
|
6362
6258
|
const { t } = useTranslation2();
|
|
@@ -6755,8 +6651,8 @@ function useSplit({
|
|
|
6755
6651
|
};
|
|
6756
6652
|
}
|
|
6757
6653
|
const pickerShell = {
|
|
6758
|
-
...
|
|
6759
|
-
openTab: (host, type, options) =>
|
|
6654
|
+
...callbacks,
|
|
6655
|
+
openTab: (host, type, options) => callbacks.openTab(host, type, { ...options, forceNewTab: true })
|
|
6760
6656
|
};
|
|
6761
6657
|
const split = {
|
|
6762
6658
|
active: activeSplit,
|
|
@@ -6922,7 +6818,7 @@ function useWorkspaceLayout(tabsState, regions) {
|
|
|
6922
6818
|
|
|
6923
6819
|
// src/ui/shell/controller/use-shell-keybindings.ts
|
|
6924
6820
|
init_define_import_meta_env();
|
|
6925
|
-
import { useEffect as useEffect11, useRef as useRef5, useState as
|
|
6821
|
+
import { useEffect as useEffect11, useRef as useRef5, useState as useState9 } from "react";
|
|
6926
6822
|
|
|
6927
6823
|
// src/ui/lib/pane-nav-hotkey.ts
|
|
6928
6824
|
init_define_import_meta_env();
|
|
@@ -7026,7 +6922,7 @@ function useShellKeybindings({
|
|
|
7026
6922
|
closeActiveTabRef.current();
|
|
7027
6923
|
});
|
|
7028
6924
|
}, []);
|
|
7029
|
-
const [commandPaletteShortcutEnabled, setCommandPaletteShortcutEnabled] =
|
|
6925
|
+
const [commandPaletteShortcutEnabled, setCommandPaletteShortcutEnabled] = useState9(() => {
|
|
7030
6926
|
const v = localStorage.getItem("commandPaletteShortcutEnabled");
|
|
7031
6927
|
return v !== null ? v === "true" : true;
|
|
7032
6928
|
});
|
|
@@ -7093,7 +6989,7 @@ function useShellKeybindings({
|
|
|
7093
6989
|
const tabDigit = getTabJumpDigit(e);
|
|
7094
6990
|
if (tabDigit !== null) {
|
|
7095
6991
|
const currentTabs = tabsRef.current.filter(
|
|
7096
|
-
(tab) => !tab.parentSplitTabId
|
|
6992
|
+
(tab) => !tab.parentSplitTabId && tab.type !== "dashboard"
|
|
7097
6993
|
);
|
|
7098
6994
|
const index = tabDigit - 1;
|
|
7099
6995
|
if (index < currentTabs.length) {
|
|
@@ -7139,7 +7035,7 @@ function useShellKeybindings({
|
|
|
7139
7035
|
|
|
7140
7036
|
// src/ui/shell/controller/use-shell-lifecycle.ts
|
|
7141
7037
|
init_define_import_meta_env();
|
|
7142
|
-
import { useCallback as useCallback5, useEffect as useEffect12, useState as
|
|
7038
|
+
import { useCallback as useCallback5, useEffect as useEffect12, useState as useState10 } from "react";
|
|
7143
7039
|
import { toast as toast3 } from "sonner";
|
|
7144
7040
|
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
7145
7041
|
var SNAPSHOT_KEYS = [
|
|
@@ -7218,12 +7114,12 @@ function useShellLifecycle({
|
|
|
7218
7114
|
}) {
|
|
7219
7115
|
const { t, i18n: i18n2 } = useTranslation3();
|
|
7220
7116
|
const { setTheme } = useTheme();
|
|
7221
|
-
const [userPrefs, setUserPrefs] =
|
|
7117
|
+
const [userPrefs, setUserPrefs] = useState10({
|
|
7222
7118
|
reopenTabsOnLogin: false
|
|
7223
7119
|
});
|
|
7224
|
-
const [userPrefsLoaded, setUserPrefsLoaded] =
|
|
7225
|
-
const [isAdmin, setIsAdmin] =
|
|
7226
|
-
const [isAppFullscreen, setIsAppFullscreen] =
|
|
7120
|
+
const [userPrefsLoaded, setUserPrefsLoaded] = useState10(false);
|
|
7121
|
+
const [isAdmin, setIsAdmin] = useState10(false);
|
|
7122
|
+
const [isAppFullscreen, setIsAppFullscreen] = useState10(
|
|
7227
7123
|
() => !!document.fullscreenElement
|
|
7228
7124
|
);
|
|
7229
7125
|
useEffect12(() => {
|
|
@@ -7354,7 +7250,7 @@ function useShellSnapshot() {
|
|
|
7354
7250
|
}
|
|
7355
7251
|
|
|
7356
7252
|
// src/ui/shell/controller/ShellControllerProvider.tsx
|
|
7357
|
-
import { jsx as
|
|
7253
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
7358
7254
|
var ShellControllerContext = createContext3(null);
|
|
7359
7255
|
var TabStageContext = createContext3(null);
|
|
7360
7256
|
function useShellController() {
|
|
@@ -7386,7 +7282,7 @@ function ShellControllerProvider({
|
|
|
7386
7282
|
useTabTypes();
|
|
7387
7283
|
const { settled: pluginsSettled } = usePluginStore();
|
|
7388
7284
|
const isMobile = useIsMobile();
|
|
7389
|
-
const [stageStore] =
|
|
7285
|
+
const [stageStore] = useState11(createTabStageStore);
|
|
7390
7286
|
const confirmRef = useRef6(null);
|
|
7391
7287
|
const openSingletonRef = useRef6(
|
|
7392
7288
|
() => void 0
|
|
@@ -7397,7 +7293,7 @@ function ShellControllerProvider({
|
|
|
7397
7293
|
});
|
|
7398
7294
|
const regions = useRegions(isMobile);
|
|
7399
7295
|
const hosts = useHostList();
|
|
7400
|
-
const [paletteOpen, setPaletteOpen] =
|
|
7296
|
+
const [paletteOpen, setPaletteOpen] = useState11(false);
|
|
7401
7297
|
const tabsState = useTabs({
|
|
7402
7298
|
hosts: hosts.list,
|
|
7403
7299
|
hostsRef: hosts.listRef,
|
|
@@ -7454,6 +7350,10 @@ function ShellControllerProvider({
|
|
|
7454
7350
|
regions.right.setView((prev) => prev === id ? null : prev);
|
|
7455
7351
|
},
|
|
7456
7352
|
openHostEditor: (draft) => requestManage({ kind: "host", hostId: null, draft }),
|
|
7353
|
+
editHost: (hostId) => {
|
|
7354
|
+
requestManage({ kind: "host", hostId: String(hostId) });
|
|
7355
|
+
if (isMobile) regions.left.setOpen(false);
|
|
7356
|
+
},
|
|
7457
7357
|
saveQuickConnect: tabsState.saveQuickConnectHost,
|
|
7458
7358
|
confirm: (options) => confirmRef.current ? confirmRef.current(options) : Promise.resolve(false)
|
|
7459
7359
|
};
|
|
@@ -7461,7 +7361,7 @@ function ShellControllerProvider({
|
|
|
7461
7361
|
useLayoutEffect2(() => {
|
|
7462
7362
|
shellImplRef.current = shellCallbacksImpl;
|
|
7463
7363
|
});
|
|
7464
|
-
const
|
|
7364
|
+
const callbacks = useMemo5(
|
|
7465
7365
|
() => ({
|
|
7466
7366
|
openTab: (...args) => shellImplRef.current.openTab(...args),
|
|
7467
7367
|
openSingletonTab: (...args) => shellImplRef.current.openSingletonTab(...args),
|
|
@@ -7471,6 +7371,7 @@ function ShellControllerProvider({
|
|
|
7471
7371
|
openRailView: (...args) => shellImplRef.current.openRailView(...args),
|
|
7472
7372
|
closeRailView: (...args) => shellImplRef.current.closeRailView(...args),
|
|
7473
7373
|
openHostEditor: (...args) => shellImplRef.current.openHostEditor?.(...args),
|
|
7374
|
+
editHost: (...args) => shellImplRef.current.editHost?.(...args),
|
|
7474
7375
|
saveQuickConnect: (...args) => shellImplRef.current.saveQuickConnect(...args),
|
|
7475
7376
|
confirm: (...args) => shellImplRef.current.confirm(...args)
|
|
7476
7377
|
}),
|
|
@@ -7478,13 +7379,13 @@ function ShellControllerProvider({
|
|
|
7478
7379
|
);
|
|
7479
7380
|
const panelCallbacks = useMemo5(
|
|
7480
7381
|
() => ({
|
|
7481
|
-
...
|
|
7382
|
+
...callbacks,
|
|
7482
7383
|
openTab: (...args) => {
|
|
7483
|
-
|
|
7384
|
+
callbacks.openTab(...args);
|
|
7484
7385
|
if (isMobile) regions.left.setOpen(false);
|
|
7485
7386
|
}
|
|
7486
7387
|
}),
|
|
7487
|
-
[
|
|
7388
|
+
[callbacks, isMobile]
|
|
7488
7389
|
);
|
|
7489
7390
|
const resizeAllTerminals = useCallback6(() => {
|
|
7490
7391
|
const id = requestAnimationFrame(() => {
|
|
@@ -7501,7 +7402,7 @@ function ShellControllerProvider({
|
|
|
7501
7402
|
tabsState,
|
|
7502
7403
|
isMobile,
|
|
7503
7404
|
paneEls: stageStore.paneEls,
|
|
7504
|
-
callbacks
|
|
7405
|
+
callbacks,
|
|
7505
7406
|
resizeAllTerminals
|
|
7506
7407
|
});
|
|
7507
7408
|
useEffect13(() => {
|
|
@@ -7526,7 +7427,7 @@ function ShellControllerProvider({
|
|
|
7526
7427
|
toggleFullscreen: lifecycle.toggleAppFullscreen
|
|
7527
7428
|
});
|
|
7528
7429
|
useEffect13(() => {
|
|
7529
|
-
setShellCallbacks(
|
|
7430
|
+
setShellCallbacks(callbacks);
|
|
7530
7431
|
});
|
|
7531
7432
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
7532
7433
|
const controller = {
|
|
@@ -7575,7 +7476,7 @@ function ShellControllerProvider({
|
|
|
7575
7476
|
active: lifecycle.isAppFullscreen,
|
|
7576
7477
|
toggle: lifecycle.toggleAppFullscreen
|
|
7577
7478
|
},
|
|
7578
|
-
callbacks
|
|
7479
|
+
callbacks,
|
|
7579
7480
|
panelCallbacks,
|
|
7580
7481
|
settings: {
|
|
7581
7482
|
username,
|
|
@@ -7592,7 +7493,7 @@ function ShellControllerProvider({
|
|
|
7592
7493
|
publishShellController(controller);
|
|
7593
7494
|
});
|
|
7594
7495
|
useEffect13(() => () => publishShellController(null), []);
|
|
7595
|
-
return /* @__PURE__ */
|
|
7496
|
+
return /* @__PURE__ */ jsx4(TabStageContext.Provider, { value: stageStore, children: /* @__PURE__ */ jsx4(ShellControllerContext.Provider, { value: controller, children }) });
|
|
7596
7497
|
}
|
|
7597
7498
|
|
|
7598
7499
|
// src/ui/lib/adaptive-polling.ts
|
|
@@ -7701,7 +7602,7 @@ import {
|
|
|
7701
7602
|
useRef as useRef7,
|
|
7702
7603
|
useMemo as useMemo6,
|
|
7703
7604
|
useSyncExternalStore as useSyncExternalStore8,
|
|
7704
|
-
useState as
|
|
7605
|
+
useState as useState12
|
|
7705
7606
|
} from "react";
|
|
7706
7607
|
|
|
7707
7608
|
// src/ui/lib/server-status-store.ts
|
|
@@ -7795,7 +7696,7 @@ var ServerStatusStore = class {
|
|
|
7795
7696
|
};
|
|
7796
7697
|
|
|
7797
7698
|
// src/ui/lib/ServerStatusContext.tsx
|
|
7798
|
-
import { jsx as
|
|
7699
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
7799
7700
|
var StatusStoreContext = createContext4(null);
|
|
7800
7701
|
var ServerStatusContext = createContext4(null);
|
|
7801
7702
|
var activeStore = null;
|
|
@@ -7812,7 +7713,7 @@ function ServerStatusProvider({
|
|
|
7812
7713
|
storeRef.current = new ServerStatusStore();
|
|
7813
7714
|
}
|
|
7814
7715
|
const store = storeRef.current;
|
|
7815
|
-
const [
|
|
7716
|
+
const [version3, setVersion] = useState12(0);
|
|
7816
7717
|
const mountedRef = useRef7(true);
|
|
7817
7718
|
const refreshInFlightRef = useRef7(null);
|
|
7818
7719
|
useEffect14(() => store.subscribeAll(() => setVersion((v) => v + 1)), [store]);
|
|
@@ -7895,9 +7796,9 @@ function ServerStatusProvider({
|
|
|
7895
7796
|
}),
|
|
7896
7797
|
// version refreshes the statuses/initialLoadComplete snapshots
|
|
7897
7798
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
7898
|
-
[
|
|
7799
|
+
[version3, refreshStatuses, getStatus]
|
|
7899
7800
|
);
|
|
7900
|
-
return /* @__PURE__ */
|
|
7801
|
+
return /* @__PURE__ */ jsx5(StatusStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx5(ServerStatusContext.Provider, { value: contextValue, children }) });
|
|
7901
7802
|
}
|
|
7902
7803
|
function useStatusStore() {
|
|
7903
7804
|
const store = useContext4(StatusStoreContext);
|
|
@@ -7947,7 +7848,7 @@ function useOptionalHostStatusEntry(hostId) {
|
|
|
7947
7848
|
|
|
7948
7849
|
// src/ui/plugin-host/bridge.ts
|
|
7949
7850
|
init_define_import_meta_env();
|
|
7950
|
-
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo8, useState as
|
|
7851
|
+
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo8, useState as useState13 } from "react";
|
|
7951
7852
|
|
|
7952
7853
|
// src/ui/shell/companions.ts
|
|
7953
7854
|
init_define_import_meta_env();
|
|
@@ -8267,7 +8168,7 @@ var pluginHostBridge = {
|
|
|
8267
8168
|
},
|
|
8268
8169
|
useSettings(pluginId, scope, hostId) {
|
|
8269
8170
|
const numericHostId = hostId === void 0 ? void 0 : Number.parseInt(String(hostId), 10);
|
|
8270
|
-
const [state2, setState] =
|
|
8171
|
+
const [state2, setState] = useState13({ values: {}, loaded: false });
|
|
8271
8172
|
useEffect15(() => {
|
|
8272
8173
|
let cancelled = false;
|
|
8273
8174
|
if (scope === "host" && !Number.isFinite(numericHostId)) return;
|
|
@@ -8323,7 +8224,7 @@ var pluginHostBridge = {
|
|
|
8323
8224
|
);
|
|
8324
8225
|
},
|
|
8325
8226
|
useCurrentUser() {
|
|
8326
|
-
const [user, setUser] =
|
|
8227
|
+
const [user, setUser] = useState13(null);
|
|
8327
8228
|
useEffect15(() => {
|
|
8328
8229
|
let cancelled = false;
|
|
8329
8230
|
loadCurrentUser().then((next) => {
|
|
@@ -8907,8 +8808,8 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8907
8808
|
},
|
|
8908
8809
|
registerOnboardingStep(step) {
|
|
8909
8810
|
requireStepId(step.id, "onboarding step");
|
|
8910
|
-
const
|
|
8911
|
-
if (!Number.isInteger(
|
|
8811
|
+
const version3 = step.version ?? 1;
|
|
8812
|
+
if (!Number.isInteger(version3) || version3 < 1) {
|
|
8912
8813
|
throw new Error(
|
|
8913
8814
|
`${pluginId}: onboarding step "${step.id}" needs a whole version of 1 or more`
|
|
8914
8815
|
);
|
|
@@ -8918,7 +8819,7 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8918
8819
|
onboardingSteps.register({
|
|
8919
8820
|
id: pluginStepKey(pluginId, step.id),
|
|
8920
8821
|
pluginId,
|
|
8921
|
-
version:
|
|
8822
|
+
version: version3,
|
|
8922
8823
|
titleKey: key(step.titleKey),
|
|
8923
8824
|
descriptionKey: step.descriptionKey ? key(step.descriptionKey) : void 0,
|
|
8924
8825
|
icon: step.icon ? withIconBoundary(pluginId, step.icon) : void 0,
|
|
@@ -9056,918 +8957,6 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
9056
8957
|
};
|
|
9057
8958
|
}
|
|
9058
8959
|
|
|
9059
|
-
// src/ui/hooks/use-installed-plugins.ts
|
|
9060
|
-
init_define_import_meta_env();
|
|
9061
|
-
import { useEffect as useEffect17, useState as useState15 } from "react";
|
|
9062
|
-
function useInstalledPlugins() {
|
|
9063
|
-
const [plugins, setPlugins] = useState15([]);
|
|
9064
|
-
useEffect17(() => {
|
|
9065
|
-
let cancelled = false;
|
|
9066
|
-
let request = 0;
|
|
9067
|
-
const load2 = () => {
|
|
9068
|
-
const current2 = ++request;
|
|
9069
|
-
void getPlugins().then((loaded) => {
|
|
9070
|
-
if (!cancelled && current2 === request) setPlugins(loaded);
|
|
9071
|
-
}).catch(() => {
|
|
9072
|
-
});
|
|
9073
|
-
};
|
|
9074
|
-
load2();
|
|
9075
|
-
window.addEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9076
|
-
return () => {
|
|
9077
|
-
cancelled = true;
|
|
9078
|
-
window.removeEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9079
|
-
};
|
|
9080
|
-
}, []);
|
|
9081
|
-
return plugins;
|
|
9082
|
-
}
|
|
9083
|
-
|
|
9084
|
-
// src/ui/settings/SettingsFields.tsx
|
|
9085
|
-
init_define_import_meta_env();
|
|
9086
|
-
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
9087
|
-
import { Fragment, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
9088
|
-
function SettingsFieldRow({
|
|
9089
|
-
pluginId,
|
|
9090
|
-
field,
|
|
9091
|
-
values,
|
|
9092
|
-
setValue,
|
|
9093
|
-
running,
|
|
9094
|
-
error,
|
|
9095
|
-
disabled = false,
|
|
9096
|
-
defaultKey
|
|
9097
|
-
}) {
|
|
9098
|
-
const { t } = useTranslation4();
|
|
9099
|
-
useSettingsComponents();
|
|
9100
|
-
const label = (key) => key ? t(pluginKey(pluginId, key)) : "";
|
|
9101
|
-
if (field.type === "custom") {
|
|
9102
|
-
const Component = getSettingsComponent(pluginId, field.component);
|
|
9103
|
-
if (!Component) return null;
|
|
9104
|
-
return /* @__PURE__ */ jsx9(
|
|
9105
|
-
Component,
|
|
9106
|
-
{
|
|
9107
|
-
pluginId,
|
|
9108
|
-
values,
|
|
9109
|
-
setValue,
|
|
9110
|
-
running
|
|
9111
|
-
}
|
|
9112
|
-
);
|
|
9113
|
-
}
|
|
9114
|
-
const value = values[field.key];
|
|
9115
|
-
const readOnly = disabled || !running;
|
|
9116
|
-
const description = field.descriptionKey ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
9117
|
-
label(field.descriptionKey),
|
|
9118
|
-
error && /* @__PURE__ */ jsx9("span", { className: "block text-destructive mt-0.5", children: error })
|
|
9119
|
-
] }) : error ? /* @__PURE__ */ jsx9("span", { className: "text-destructive", children: error }) : void 0;
|
|
9120
|
-
const control = /* @__PURE__ */ jsx9(
|
|
9121
|
-
FieldControl,
|
|
9122
|
-
{
|
|
9123
|
-
pluginId,
|
|
9124
|
-
field,
|
|
9125
|
-
value,
|
|
9126
|
-
setValue,
|
|
9127
|
-
readOnly
|
|
9128
|
-
}
|
|
9129
|
-
);
|
|
9130
|
-
if (field.type === "boolean") {
|
|
9131
|
-
return /* @__PURE__ */ jsx9(
|
|
9132
|
-
SettingRow,
|
|
9133
|
-
{
|
|
9134
|
-
label: label(field.labelKey),
|
|
9135
|
-
description,
|
|
9136
|
-
badge: error ? t("common.error") : void 0,
|
|
9137
|
-
defaultKey,
|
|
9138
|
-
children: control
|
|
9139
|
-
}
|
|
9140
|
-
);
|
|
9141
|
-
}
|
|
9142
|
-
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: [
|
|
9143
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
|
|
9144
|
-
/* @__PURE__ */ jsx9("span", { className: "text-sm font-medium leading-snug", children: label(field.labelKey) }),
|
|
9145
|
-
error && /* @__PURE__ */ jsx9("span", { className: "text-[10px] font-bold text-warning border border-warning/40 px-1 shrink-0", children: t("common.error") }),
|
|
9146
|
-
defaultKey && /* @__PURE__ */ jsx9(HostDefaultBadge, { settingKey: defaultKey })
|
|
9147
|
-
] }),
|
|
9148
|
-
description && /* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground leading-snug", children: description }),
|
|
9149
|
-
/* @__PURE__ */ jsx9("div", { className: "min-w-0", children: control })
|
|
9150
|
-
] }) });
|
|
9151
|
-
}
|
|
9152
|
-
function FieldControl({
|
|
9153
|
-
pluginId,
|
|
9154
|
-
field,
|
|
9155
|
-
value,
|
|
9156
|
-
setValue,
|
|
9157
|
-
readOnly
|
|
9158
|
-
}) {
|
|
9159
|
-
const { t } = useTranslation4();
|
|
9160
|
-
const label = (key) => key ? t(pluginKey(pluginId, key)) : "";
|
|
9161
|
-
const placeholder = field.placeholderKey ? label(field.placeholderKey) : void 0;
|
|
9162
|
-
switch (field.type) {
|
|
9163
|
-
case "boolean":
|
|
9164
|
-
return /* @__PURE__ */ jsx9(
|
|
9165
|
-
FakeSwitch,
|
|
9166
|
-
{
|
|
9167
|
-
checked: value === true,
|
|
9168
|
-
disabled: readOnly,
|
|
9169
|
-
onChange: (next) => setValue(field.key, next)
|
|
9170
|
-
}
|
|
9171
|
-
);
|
|
9172
|
-
case "number":
|
|
9173
|
-
return /* @__PURE__ */ jsx9(
|
|
9174
|
-
Input,
|
|
9175
|
-
{
|
|
9176
|
-
type: "number",
|
|
9177
|
-
className: "h-8 w-full max-w-40 text-sm",
|
|
9178
|
-
disabled: readOnly,
|
|
9179
|
-
min: field.min,
|
|
9180
|
-
max: field.max,
|
|
9181
|
-
placeholder,
|
|
9182
|
-
value: value === void 0 || value === null ? "" : String(value),
|
|
9183
|
-
onChange: (event) => setValue(
|
|
9184
|
-
field.key,
|
|
9185
|
-
event.target.value === "" ? null : Number(event.target.value)
|
|
9186
|
-
)
|
|
9187
|
-
}
|
|
9188
|
-
);
|
|
9189
|
-
case "select":
|
|
9190
|
-
return /* @__PURE__ */ jsxs2(
|
|
9191
|
-
Select,
|
|
9192
|
-
{
|
|
9193
|
-
disabled: readOnly,
|
|
9194
|
-
value: typeof value === "string" ? value : "",
|
|
9195
|
-
onValueChange: (next) => setValue(field.key, next),
|
|
9196
|
-
children: [
|
|
9197
|
-
/* @__PURE__ */ jsx9(SelectTrigger, { className: "h-8 w-full min-w-0 text-sm", children: /* @__PURE__ */ jsx9(SelectValue, { placeholder }) }),
|
|
9198
|
-
/* @__PURE__ */ jsx9(SelectContent, { children: (field.options ?? []).map((option) => /* @__PURE__ */ jsx9(SelectItem, { value: option.value, children: label(option.labelKey) }, option.value)) })
|
|
9199
|
-
]
|
|
9200
|
-
}
|
|
9201
|
-
);
|
|
9202
|
-
case "multiselect": {
|
|
9203
|
-
const selected = Array.isArray(value) ? value : [];
|
|
9204
|
-
return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-1.5", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs2(
|
|
9205
|
-
"label",
|
|
9206
|
-
{
|
|
9207
|
-
className: "flex items-center gap-2 text-xs text-muted-foreground",
|
|
9208
|
-
children: [
|
|
9209
|
-
/* @__PURE__ */ jsx9(
|
|
9210
|
-
Checkbox2,
|
|
9211
|
-
{
|
|
9212
|
-
disabled: readOnly,
|
|
9213
|
-
checked: selected.includes(option.value),
|
|
9214
|
-
onCheckedChange: (checked) => setValue(
|
|
9215
|
-
field.key,
|
|
9216
|
-
checked ? [...selected, option.value] : selected.filter((entry) => entry !== option.value)
|
|
9217
|
-
)
|
|
9218
|
-
}
|
|
9219
|
-
),
|
|
9220
|
-
/* @__PURE__ */ jsx9("span", { children: label(option.labelKey) })
|
|
9221
|
-
]
|
|
9222
|
-
},
|
|
9223
|
-
option.value
|
|
9224
|
-
)) });
|
|
9225
|
-
}
|
|
9226
|
-
case "secret":
|
|
9227
|
-
return /* @__PURE__ */ jsx9(
|
|
9228
|
-
SecretControl,
|
|
9229
|
-
{
|
|
9230
|
-
field,
|
|
9231
|
-
value,
|
|
9232
|
-
setValue,
|
|
9233
|
-
readOnly,
|
|
9234
|
-
placeholder
|
|
9235
|
-
}
|
|
9236
|
-
);
|
|
9237
|
-
case "textarea":
|
|
9238
|
-
case "json":
|
|
9239
|
-
return /* @__PURE__ */ jsx9(
|
|
9240
|
-
Textarea,
|
|
9241
|
-
{
|
|
9242
|
-
className: "w-full text-sm font-mono min-h-16",
|
|
9243
|
-
disabled: readOnly,
|
|
9244
|
-
placeholder,
|
|
9245
|
-
value: typeof value === "string" ? value : value === void 0 || value === null ? "" : JSON.stringify(value, null, 2),
|
|
9246
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9247
|
-
}
|
|
9248
|
-
);
|
|
9249
|
-
default:
|
|
9250
|
-
return /* @__PURE__ */ jsx9(
|
|
9251
|
-
Input,
|
|
9252
|
-
{
|
|
9253
|
-
className: "h-8 w-full text-sm",
|
|
9254
|
-
disabled: readOnly,
|
|
9255
|
-
placeholder,
|
|
9256
|
-
value: typeof value === "string" ? value : "",
|
|
9257
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9258
|
-
}
|
|
9259
|
-
);
|
|
9260
|
-
}
|
|
9261
|
-
}
|
|
9262
|
-
function SecretControl({
|
|
9263
|
-
field,
|
|
9264
|
-
value,
|
|
9265
|
-
setValue,
|
|
9266
|
-
readOnly,
|
|
9267
|
-
placeholder
|
|
9268
|
-
}) {
|
|
9269
|
-
const { t } = useTranslation4();
|
|
9270
|
-
const redacted = isRedactedSecret(value);
|
|
9271
|
-
const stored = redacted && value.set;
|
|
9272
|
-
if (redacted) {
|
|
9273
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
9274
|
-
/* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: stored ? t("settings.secretSet") : t("settings.secretNotSet") }),
|
|
9275
|
-
/* @__PURE__ */ jsx9(
|
|
9276
|
-
Button,
|
|
9277
|
-
{
|
|
9278
|
-
variant: "outline",
|
|
9279
|
-
size: "sm",
|
|
9280
|
-
className: "h-7 text-xs",
|
|
9281
|
-
disabled: readOnly,
|
|
9282
|
-
onClick: () => setValue(field.key, ""),
|
|
9283
|
-
children: stored ? t("settings.secretReplace") : t("common.edit")
|
|
9284
|
-
}
|
|
9285
|
-
)
|
|
9286
|
-
] });
|
|
9287
|
-
}
|
|
9288
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
9289
|
-
/* @__PURE__ */ jsx9("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx9(
|
|
9290
|
-
PasswordInput,
|
|
9291
|
-
{
|
|
9292
|
-
className: "h-8 w-full text-sm",
|
|
9293
|
-
disabled: readOnly,
|
|
9294
|
-
placeholder,
|
|
9295
|
-
value: typeof value === "string" ? value : "",
|
|
9296
|
-
onChange: (event) => setValue(field.key, event.target.value)
|
|
9297
|
-
}
|
|
9298
|
-
) }),
|
|
9299
|
-
/* @__PURE__ */ jsx9(
|
|
9300
|
-
Button,
|
|
9301
|
-
{
|
|
9302
|
-
variant: "ghost",
|
|
9303
|
-
size: "sm",
|
|
9304
|
-
className: "h-7 text-xs",
|
|
9305
|
-
disabled: readOnly,
|
|
9306
|
-
onClick: () => setValue(field.key, { set: stored }),
|
|
9307
|
-
children: t("common.cancel")
|
|
9308
|
-
}
|
|
9309
|
-
)
|
|
9310
|
-
] });
|
|
9311
|
-
}
|
|
9312
|
-
|
|
9313
|
-
// src/ui/settings/HostPluginSections.tsx
|
|
9314
|
-
init_define_import_meta_env();
|
|
9315
|
-
import { useMemo as useMemo9 } from "react";
|
|
9316
|
-
import { useTranslation as useTranslation5 } from "react-i18next";
|
|
9317
|
-
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
9318
|
-
function usePluginHostSections() {
|
|
9319
|
-
const plugins = useInstalledPlugins();
|
|
9320
|
-
return useMemo9(
|
|
9321
|
-
() => plugins.filter((plugin) => {
|
|
9322
|
-
if (!plugin.enabled) return false;
|
|
9323
|
-
const host = plugin.contributes?.settings?.host;
|
|
9324
|
-
return !!host && (hasVisibleFields(host.fields) || !!host.enableKey);
|
|
9325
|
-
}),
|
|
9326
|
-
[plugins]
|
|
9327
|
-
);
|
|
9328
|
-
}
|
|
9329
|
-
function hostFieldDefaults(plugin) {
|
|
9330
|
-
const host = plugin.contributes?.settings?.host;
|
|
9331
|
-
if (!host) return {};
|
|
9332
|
-
const defaults3 = {};
|
|
9333
|
-
if (host.enableKey) defaults3[host.enableKey] = host.enableDefault ?? false;
|
|
9334
|
-
for (const field of host.fields) {
|
|
9335
|
-
if (field.default !== void 0) defaults3[field.key] = field.default;
|
|
9336
|
-
}
|
|
9337
|
-
return defaults3;
|
|
9338
|
-
}
|
|
9339
|
-
function HostPluginSections({
|
|
9340
|
-
plugins,
|
|
9341
|
-
values,
|
|
9342
|
-
setValue
|
|
9343
|
-
}) {
|
|
9344
|
-
if (plugins.length === 0) return null;
|
|
9345
|
-
return /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-2", children: plugins.map((plugin) => /* @__PURE__ */ jsx10(
|
|
9346
|
-
HostPluginSection,
|
|
9347
|
-
{
|
|
9348
|
-
plugin,
|
|
9349
|
-
values: values[plugin.id] ?? {},
|
|
9350
|
-
setValue: (key, value) => setValue(plugin.id, key, value)
|
|
9351
|
-
},
|
|
9352
|
-
plugin.id
|
|
9353
|
-
)) });
|
|
9354
|
-
}
|
|
9355
|
-
function HostFeatureFields({
|
|
9356
|
-
form,
|
|
9357
|
-
updateForm
|
|
9358
|
-
}) {
|
|
9359
|
-
const pluginId = usePluginScope();
|
|
9360
|
-
const plugin = usePluginHostSections().find((p) => p.id === pluginId);
|
|
9361
|
-
if (!plugin) return null;
|
|
9362
|
-
const values = form?.pluginSettings ?? {};
|
|
9363
|
-
return /* @__PURE__ */ jsx10(
|
|
9364
|
-
HostPluginSection,
|
|
9365
|
-
{
|
|
9366
|
-
plugin,
|
|
9367
|
-
values: values[plugin.id] ?? {},
|
|
9368
|
-
setValue: (key, value) => updateForm((current2) => {
|
|
9369
|
-
const all = current2.pluginSettings ?? {};
|
|
9370
|
-
return {
|
|
9371
|
-
...current2,
|
|
9372
|
-
pluginSettings: {
|
|
9373
|
-
...all,
|
|
9374
|
-
[plugin.id]: { ...all[plugin.id] ?? {}, [key]: value }
|
|
9375
|
-
}
|
|
9376
|
-
};
|
|
9377
|
-
})
|
|
9378
|
-
}
|
|
9379
|
-
);
|
|
9380
|
-
}
|
|
9381
|
-
function HostPluginSection({
|
|
9382
|
-
plugin,
|
|
9383
|
-
values,
|
|
9384
|
-
setValue
|
|
9385
|
-
}) {
|
|
9386
|
-
const { t } = useTranslation5();
|
|
9387
|
-
const host = plugin.contributes?.settings?.host;
|
|
9388
|
-
if (!host) return null;
|
|
9389
|
-
const shown = { ...hostFieldDefaults(plugin), ...values };
|
|
9390
|
-
const running = plugin.enabled && plugin.state !== "failed";
|
|
9391
|
-
const enableKey = host.enableKey;
|
|
9392
|
-
const enabled = enableKey ? shown[enableKey] === true : true;
|
|
9393
|
-
return /* @__PURE__ */ jsxs3(
|
|
9394
|
-
SectionCard,
|
|
9395
|
-
{
|
|
9396
|
-
title: pluginName(t, plugin),
|
|
9397
|
-
icon: /* @__PURE__ */ jsx10(PluginIcon, { name: plugin.icon, className: "size-3.5" }),
|
|
9398
|
-
action: /* @__PURE__ */ jsx10(DocsLink, { href: plugin.docs }),
|
|
9399
|
-
children: [
|
|
9400
|
-
!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", {
|
|
9401
|
-
name: pluginName(t, plugin)
|
|
9402
|
-
}) }),
|
|
9403
|
-
enableKey && /* @__PURE__ */ jsx10(
|
|
9404
|
-
SettingsFieldRow,
|
|
9405
|
-
{
|
|
9406
|
-
pluginId: plugin.id,
|
|
9407
|
-
field: {
|
|
9408
|
-
key: enableKey,
|
|
9409
|
-
type: "boolean",
|
|
9410
|
-
labelKey: host.enableLabelKey,
|
|
9411
|
-
descriptionKey: host.enableDescriptionKey
|
|
9412
|
-
},
|
|
9413
|
-
values: shown,
|
|
9414
|
-
setValue,
|
|
9415
|
-
running,
|
|
9416
|
-
defaultKey: `${plugin.id}.${enableKey}`
|
|
9417
|
-
}
|
|
9418
|
-
),
|
|
9419
|
-
enabled && host.fields.filter((field) => isFieldShown(field, shown)).map((field) => /* @__PURE__ */ jsx10(
|
|
9420
|
-
SettingsFieldRow,
|
|
9421
|
-
{
|
|
9422
|
-
pluginId: plugin.id,
|
|
9423
|
-
field,
|
|
9424
|
-
values: shown,
|
|
9425
|
-
setValue,
|
|
9426
|
-
running,
|
|
9427
|
-
defaultKey: `${plugin.id}.${field.key}`
|
|
9428
|
-
},
|
|
9429
|
-
field.key
|
|
9430
|
-
))
|
|
9431
|
-
]
|
|
9432
|
-
}
|
|
9433
|
-
);
|
|
9434
|
-
}
|
|
9435
|
-
|
|
9436
|
-
// src/ui/shell/ActionSlot.tsx
|
|
9437
|
-
init_define_import_meta_env();
|
|
9438
|
-
import React5 from "react";
|
|
9439
|
-
import { useTranslation as useTranslation6 } from "react-i18next";
|
|
9440
|
-
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9441
|
-
function ActionSlot({
|
|
9442
|
-
slotId,
|
|
9443
|
-
context,
|
|
9444
|
-
className,
|
|
9445
|
-
enabled = true,
|
|
9446
|
-
renderItem,
|
|
9447
|
-
hideLabels,
|
|
9448
|
-
when
|
|
9449
|
-
}) {
|
|
9450
|
-
const { t } = useTranslation6();
|
|
9451
|
-
const contributions2 = useActionSlot(slotId, when).filter(
|
|
9452
|
-
(contribution) => contribution.kind !== "component"
|
|
9453
|
-
);
|
|
9454
|
-
if (!enabled || contributions2.length === 0) return null;
|
|
9455
|
-
return /* @__PURE__ */ jsx11(Fragment2, { children: contributions2.map((contribution) => {
|
|
9456
|
-
const invoke = () => {
|
|
9457
|
-
void invokeAction(contribution.actionId, ...context?.() ?? []);
|
|
9458
|
-
};
|
|
9459
|
-
if (renderItem) {
|
|
9460
|
-
return /* @__PURE__ */ jsx11(React5.Fragment, { children: renderItem(contribution, invoke) }, contribution.actionId);
|
|
9461
|
-
}
|
|
9462
|
-
const Icon = contribution.icon;
|
|
9463
|
-
const label = t(contribution.titleKey);
|
|
9464
|
-
return /* @__PURE__ */ jsxs4(
|
|
9465
|
-
"button",
|
|
9466
|
-
{
|
|
9467
|
-
type: "button",
|
|
9468
|
-
className,
|
|
9469
|
-
"aria-label": label,
|
|
9470
|
-
title: label,
|
|
9471
|
-
onClick: invoke,
|
|
9472
|
-
children: [
|
|
9473
|
-
Icon && /* @__PURE__ */ jsx11(Icon, { className: "size-4 shrink-0" }),
|
|
9474
|
-
!hideLabels && label
|
|
9475
|
-
]
|
|
9476
|
-
},
|
|
9477
|
-
contribution.actionId
|
|
9478
|
-
);
|
|
9479
|
-
}) });
|
|
9480
|
-
}
|
|
9481
|
-
function ComponentSlot({
|
|
9482
|
-
slotId,
|
|
9483
|
-
props,
|
|
9484
|
-
when
|
|
9485
|
-
}) {
|
|
9486
|
-
const contributions2 = useActionSlot(slotId, when).filter(
|
|
9487
|
-
(contribution) => contribution.kind === "component" && contribution.component
|
|
9488
|
-
);
|
|
9489
|
-
if (contributions2.length === 0) return null;
|
|
9490
|
-
return /* @__PURE__ */ jsx11(Fragment2, { children: contributions2.map((contribution) => {
|
|
9491
|
-
const Contributed = contribution.component;
|
|
9492
|
-
return /* @__PURE__ */ jsx11(Contributed, { ...props ?? {} }, contribution.actionId);
|
|
9493
|
-
}) });
|
|
9494
|
-
}
|
|
9495
|
-
|
|
9496
|
-
// src/ui/shell/tab-handles.ts
|
|
9497
|
-
init_define_import_meta_env();
|
|
9498
|
-
import { useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
9499
|
-
var version3 = 0;
|
|
9500
|
-
var listeners8 = /* @__PURE__ */ new Set();
|
|
9501
|
-
var callbacks = /* @__PURE__ */ new WeakMap();
|
|
9502
|
-
function subscribe5(listener) {
|
|
9503
|
-
listeners8.add(listener);
|
|
9504
|
-
return () => listeners8.delete(listener);
|
|
9505
|
-
}
|
|
9506
|
-
function trackTabHandle(ref) {
|
|
9507
|
-
if (!ref) return void 0;
|
|
9508
|
-
let callback = callbacks.get(ref);
|
|
9509
|
-
if (!callback) {
|
|
9510
|
-
callback = (value) => {
|
|
9511
|
-
if (ref.current === value) return;
|
|
9512
|
-
ref.current = value;
|
|
9513
|
-
version3 += 1;
|
|
9514
|
-
for (const listener of listeners8) listener();
|
|
9515
|
-
};
|
|
9516
|
-
callbacks.set(ref, callback);
|
|
9517
|
-
}
|
|
9518
|
-
return callback;
|
|
9519
|
-
}
|
|
9520
|
-
function useTabHandlesVersion() {
|
|
9521
|
-
return useSyncExternalStore11(
|
|
9522
|
-
subscribe5,
|
|
9523
|
-
() => version3,
|
|
9524
|
-
() => version3
|
|
9525
|
-
);
|
|
9526
|
-
}
|
|
9527
|
-
|
|
9528
|
-
// src/ui/plugin-host/PluginViewPlaceholder.tsx
|
|
9529
|
-
init_define_import_meta_env();
|
|
9530
|
-
import { useTranslation as useTranslation7 } from "react-i18next";
|
|
9531
|
-
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
9532
|
-
function PluginViewPlaceholder({
|
|
9533
|
-
kind,
|
|
9534
|
-
viewId,
|
|
9535
|
-
compact = false
|
|
9536
|
-
}) {
|
|
9537
|
-
const { t } = useTranslation7();
|
|
9538
|
-
usePluginStore();
|
|
9539
|
-
const { has } = usePermissions();
|
|
9540
|
-
const { status, owner } = unregisteredViewStatus(kind, viewId);
|
|
9541
|
-
const name = owner ? pluginName(t, owner.summary) : viewId;
|
|
9542
|
-
if (status === "loading") {
|
|
9543
|
-
return /* @__PURE__ */ jsx12(
|
|
9544
|
-
"div",
|
|
9545
|
-
{
|
|
9546
|
-
className: "flex h-full w-full items-center justify-center",
|
|
9547
|
-
"aria-label": t("plugins.runtime.loading", { name }),
|
|
9548
|
-
children: /* @__PURE__ */ jsx12("div", { className: "size-5 rounded-full border-2 border-muted-foreground/30 border-t-muted-foreground/70 animate-spin" })
|
|
9549
|
-
}
|
|
9550
|
-
);
|
|
9551
|
-
}
|
|
9552
|
-
const title = status === "failed" ? t("plugins.runtime.failed", { name }) : owner ? t("plugins.runtime.needsPlugin", { name }) : t("plugins.runtime.needsUnknownPlugin");
|
|
9553
|
-
const hint = status === "failed" ? t("plugins.runtime.failedHint") : status === "disabled" ? t("plugins.runtime.disabledHint") : t("plugins.runtime.missingHint");
|
|
9554
|
-
return /* @__PURE__ */ jsxs5(
|
|
9555
|
-
"div",
|
|
9556
|
-
{
|
|
9557
|
-
"data-testid": "plugin-view-placeholder",
|
|
9558
|
-
"data-status": status,
|
|
9559
|
-
className: `flex h-full w-full flex-col items-center justify-center gap-2 text-center ${compact ? "p-3" : "p-6"}`,
|
|
9560
|
-
children: [
|
|
9561
|
-
/* @__PURE__ */ jsx12(CircleSlash, { className: "size-6 text-muted-foreground/40" }),
|
|
9562
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm font-semibold text-muted-foreground", children: title }),
|
|
9563
|
-
/* @__PURE__ */ jsx12("span", { className: "text-xs text-muted-foreground/70", children: hint }),
|
|
9564
|
-
!compact && status !== "failed" && has("admin.plugins.manage") && /* @__PURE__ */ jsx12(
|
|
9565
|
-
Button,
|
|
9566
|
-
{
|
|
9567
|
-
variant: "outline",
|
|
9568
|
-
size: "sm",
|
|
9569
|
-
className: "mt-1",
|
|
9570
|
-
onClick: () => window.dispatchEvent(new CustomEvent(OPEN_PLUGINS_EVENT)),
|
|
9571
|
-
children: t("plugins.manager.browsePlugins")
|
|
9572
|
-
}
|
|
9573
|
-
)
|
|
9574
|
-
]
|
|
9575
|
-
}
|
|
9576
|
-
);
|
|
9577
|
-
}
|
|
9578
|
-
|
|
9579
|
-
// src/ui/lib/adaptive-resource-budget.ts
|
|
9580
|
-
init_define_import_meta_env();
|
|
9581
|
-
|
|
9582
|
-
// src/ui/lib/local-adaptive-engine.ts
|
|
9583
|
-
init_define_import_meta_env();
|
|
9584
|
-
var LOCAL_ADAPTIVE_ENGINE_KEY = "termix.local.adaptive-engine.v1";
|
|
9585
|
-
var VERSION = 1;
|
|
9586
|
-
var HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9587
|
-
var MAX_SCOPES = 128;
|
|
9588
|
-
var MAX_ACTIONS_PER_SCOPE = 12;
|
|
9589
|
-
var DEFAULT_MIN_EVIDENCE = 2.5;
|
|
9590
|
-
var DEFAULT_MIN_SHARE = 0.6;
|
|
9591
|
-
var DEFAULT_MIN_MARGIN = 1;
|
|
9592
|
-
var EWMA_ALPHA = 0.25;
|
|
9593
|
-
function emptyStore() {
|
|
9594
|
-
return { version: VERSION, scopes: {} };
|
|
9595
|
-
}
|
|
9596
|
-
function finiteNonNegative(value) {
|
|
9597
|
-
return Number.isFinite(value) && Number(value) >= 0 ? Number(value) : 0;
|
|
9598
|
-
}
|
|
9599
|
-
function sanitizeAction(value) {
|
|
9600
|
-
if (!value || typeof value !== "object") return null;
|
|
9601
|
-
const stat = value;
|
|
9602
|
-
if (!Number.isFinite(stat.weight) || Number(stat.weight) < 0 || !Number.isFinite(stat.updatedAt)) {
|
|
9603
|
-
return null;
|
|
9604
|
-
}
|
|
9605
|
-
const latencyEwmaMs = finiteNonNegative(stat.latencyEwmaMs);
|
|
9606
|
-
return {
|
|
9607
|
-
weight: Number(stat.weight),
|
|
9608
|
-
updatedAt: Number(stat.updatedAt),
|
|
9609
|
-
observations: finiteNonNegative(stat.observations),
|
|
9610
|
-
successes: finiteNonNegative(stat.successes),
|
|
9611
|
-
cancellations: finiteNonNegative(stat.cancellations),
|
|
9612
|
-
fallbacks: finiteNonNegative(stat.fallbacks),
|
|
9613
|
-
...latencyEwmaMs > 0 ? { latencyEwmaMs } : {}
|
|
9614
|
-
};
|
|
9615
|
-
}
|
|
9616
|
-
function sanitizeStore(value) {
|
|
9617
|
-
if (!value || typeof value !== "object") return emptyStore();
|
|
9618
|
-
const candidate = value;
|
|
9619
|
-
if (candidate.version !== VERSION || !candidate.scopes || typeof candidate.scopes !== "object" || Array.isArray(candidate.scopes)) {
|
|
9620
|
-
return emptyStore();
|
|
9621
|
-
}
|
|
9622
|
-
const scopes2 = {};
|
|
9623
|
-
for (const [scope, rawScope] of Object.entries(candidate.scopes)) {
|
|
9624
|
-
if (!rawScope || typeof rawScope !== "object") continue;
|
|
9625
|
-
const value2 = rawScope;
|
|
9626
|
-
if (!Number.isFinite(value2.updatedAt) || !value2.actions || typeof value2.actions !== "object" || Array.isArray(value2.actions)) {
|
|
9627
|
-
continue;
|
|
9628
|
-
}
|
|
9629
|
-
const actions4 = {};
|
|
9630
|
-
for (const [action, rawStat] of Object.entries(value2.actions)) {
|
|
9631
|
-
const stat = sanitizeAction(rawStat);
|
|
9632
|
-
if (stat) actions4[action] = stat;
|
|
9633
|
-
}
|
|
9634
|
-
scopes2[scope] = { actions: actions4, updatedAt: Number(value2.updatedAt) };
|
|
9635
|
-
}
|
|
9636
|
-
return { version: VERSION, scopes: scopes2 };
|
|
9637
|
-
}
|
|
9638
|
-
function readStore() {
|
|
9639
|
-
if (typeof localStorage === "undefined") return emptyStore();
|
|
9640
|
-
try {
|
|
9641
|
-
return sanitizeStore(
|
|
9642
|
-
JSON.parse(localStorage.getItem(LOCAL_ADAPTIVE_ENGINE_KEY) ?? "null")
|
|
9643
|
-
);
|
|
9644
|
-
} catch {
|
|
9645
|
-
return emptyStore();
|
|
9646
|
-
}
|
|
9647
|
-
}
|
|
9648
|
-
function writeStore(store) {
|
|
9649
|
-
if (typeof localStorage === "undefined") return;
|
|
9650
|
-
try {
|
|
9651
|
-
localStorage.setItem(LOCAL_ADAPTIVE_ENGINE_KEY, JSON.stringify(store));
|
|
9652
|
-
} catch {
|
|
9653
|
-
}
|
|
9654
|
-
}
|
|
9655
|
-
function decayedWeight(stat, now) {
|
|
9656
|
-
const age = Math.max(0, now - stat.updatedAt);
|
|
9657
|
-
return stat.weight * 2 ** (-age / HALF_LIFE_MS);
|
|
9658
|
-
}
|
|
9659
|
-
function trimStore(store, now) {
|
|
9660
|
-
for (const scope of Object.values(store.scopes)) {
|
|
9661
|
-
scope.actions = Object.fromEntries(
|
|
9662
|
-
Object.entries(scope.actions).sort(
|
|
9663
|
-
([, a], [, b]) => decayedWeight(b, now) - decayedWeight(a, now) || b.updatedAt - a.updatedAt
|
|
9664
|
-
).slice(0, MAX_ACTIONS_PER_SCOPE)
|
|
9665
|
-
);
|
|
9666
|
-
}
|
|
9667
|
-
store.scopes = Object.fromEntries(
|
|
9668
|
-
Object.entries(store.scopes).sort(([, a], [, b]) => b.updatedAt - a.updatedAt).slice(0, MAX_SCOPES)
|
|
9669
|
-
);
|
|
9670
|
-
}
|
|
9671
|
-
function updateEwma(previous, value) {
|
|
9672
|
-
return previous === void 0 ? value : previous + EWMA_ALPHA * (value - previous);
|
|
9673
|
-
}
|
|
9674
|
-
function getActionStats(store, scope, action, now) {
|
|
9675
|
-
const scopeStats = store.scopes[scope] ?? { actions: {}, updatedAt: now };
|
|
9676
|
-
return [
|
|
9677
|
-
scopeStats,
|
|
9678
|
-
scopeStats.actions[action] ?? {
|
|
9679
|
-
weight: 0,
|
|
9680
|
-
updatedAt: now,
|
|
9681
|
-
observations: 0,
|
|
9682
|
-
successes: 0,
|
|
9683
|
-
cancellations: 0,
|
|
9684
|
-
fallbacks: 0
|
|
9685
|
-
}
|
|
9686
|
-
];
|
|
9687
|
-
}
|
|
9688
|
-
function saveActionStats(store, scope, action, scopeStats, actionStats, now) {
|
|
9689
|
-
scopeStats.actions[action] = actionStats;
|
|
9690
|
-
scopeStats.updatedAt = now;
|
|
9691
|
-
store.scopes[scope] = scopeStats;
|
|
9692
|
-
trimStore(store, now);
|
|
9693
|
-
writeStore(store);
|
|
9694
|
-
}
|
|
9695
|
-
function recordLocalAdaptiveChoice(scope, action, now = Date.now()) {
|
|
9696
|
-
if (!scope || !action) return;
|
|
9697
|
-
const store = readStore();
|
|
9698
|
-
const [scopeStats, previous] = getActionStats(store, scope, action, now);
|
|
9699
|
-
saveActionStats(
|
|
9700
|
-
store,
|
|
9701
|
-
scope,
|
|
9702
|
-
action,
|
|
9703
|
-
scopeStats,
|
|
9704
|
-
{
|
|
9705
|
-
...previous,
|
|
9706
|
-
weight: decayedWeight(previous, now) + 1,
|
|
9707
|
-
updatedAt: now
|
|
9708
|
-
},
|
|
9709
|
-
now
|
|
9710
|
-
);
|
|
9711
|
-
}
|
|
9712
|
-
function recordLocalAdaptiveOutcome(scope, action, outcome, now = Date.now()) {
|
|
9713
|
-
if (!scope || !action || !Object.values(outcome).some((v) => v !== void 0)) {
|
|
9714
|
-
return;
|
|
9715
|
-
}
|
|
9716
|
-
const store = readStore();
|
|
9717
|
-
const [scopeStats, previous] = getActionStats(store, scope, action, now);
|
|
9718
|
-
const latency = finiteNonNegative(outcome.latencyMs);
|
|
9719
|
-
saveActionStats(
|
|
9720
|
-
store,
|
|
9721
|
-
scope,
|
|
9722
|
-
action,
|
|
9723
|
-
scopeStats,
|
|
9724
|
-
{
|
|
9725
|
-
...previous,
|
|
9726
|
-
updatedAt: now,
|
|
9727
|
-
observations: previous.observations + 1,
|
|
9728
|
-
successes: previous.successes + (outcome.success === true ? 1 : 0),
|
|
9729
|
-
cancellations: previous.cancellations + (outcome.cancelled === true ? 1 : 0),
|
|
9730
|
-
fallbacks: previous.fallbacks + (outcome.fallback === true ? 1 : 0),
|
|
9731
|
-
...latency > 0 ? { latencyEwmaMs: updateEwma(previous.latencyEwmaMs, latency) } : {}
|
|
9732
|
-
},
|
|
9733
|
-
now
|
|
9734
|
-
);
|
|
9735
|
-
}
|
|
9736
|
-
function chooseLocalAdaptiveAction({
|
|
9737
|
-
scope,
|
|
9738
|
-
candidates,
|
|
9739
|
-
fallback,
|
|
9740
|
-
now = Date.now(),
|
|
9741
|
-
ttlMs = 5 * 60 * 1e3,
|
|
9742
|
-
minEvidence = DEFAULT_MIN_EVIDENCE,
|
|
9743
|
-
minShare = DEFAULT_MIN_SHARE,
|
|
9744
|
-
minMargin = DEFAULT_MIN_MARGIN
|
|
9745
|
-
}) {
|
|
9746
|
-
const expiresAt = now + Math.max(0, ttlMs);
|
|
9747
|
-
const stats = readStore().scopes[scope]?.actions;
|
|
9748
|
-
if (!stats || candidates.length === 0) {
|
|
9749
|
-
return { action: fallback, confidence: 0, reason: "fallback", expiresAt };
|
|
9750
|
-
}
|
|
9751
|
-
const ranked = candidates.map((action) => ({
|
|
9752
|
-
action,
|
|
9753
|
-
weight: stats[action] ? decayedWeight(stats[action], now) : 0
|
|
9754
|
-
})).sort((a, b) => b.weight - a.weight);
|
|
9755
|
-
const total = ranked.reduce((sum, item) => sum + item.weight, 0);
|
|
9756
|
-
const [best, second] = ranked;
|
|
9757
|
-
if (!best || total <= 0) {
|
|
9758
|
-
return { action: fallback, confidence: 0, reason: "fallback", expiresAt };
|
|
9759
|
-
}
|
|
9760
|
-
const share = best.weight / total;
|
|
9761
|
-
const margin = best.weight - (second?.weight ?? 0);
|
|
9762
|
-
const confidence = Math.min(
|
|
9763
|
-
1,
|
|
9764
|
-
best.weight / Math.max(minEvidence, Number.EPSILON),
|
|
9765
|
-
share / Math.max(minShare, Number.EPSILON),
|
|
9766
|
-
margin / Math.max(minMargin, Number.EPSILON)
|
|
9767
|
-
);
|
|
9768
|
-
const learned = best.weight >= minEvidence && share >= minShare && margin >= minMargin;
|
|
9769
|
-
return {
|
|
9770
|
-
action: learned ? best.action : fallback,
|
|
9771
|
-
confidence,
|
|
9772
|
-
reason: learned ? "learned" : "insufficient-evidence",
|
|
9773
|
-
expiresAt
|
|
9774
|
-
};
|
|
9775
|
-
}
|
|
9776
|
-
function getLocalAdaptiveStats(scope) {
|
|
9777
|
-
return readStore().scopes[scope]?.actions ?? {};
|
|
9778
|
-
}
|
|
9779
|
-
function clearLocalAdaptiveEngine() {
|
|
9780
|
-
if (typeof localStorage === "undefined") return;
|
|
9781
|
-
try {
|
|
9782
|
-
localStorage.removeItem(LOCAL_ADAPTIVE_ENGINE_KEY);
|
|
9783
|
-
} catch {
|
|
9784
|
-
}
|
|
9785
|
-
}
|
|
9786
|
-
|
|
9787
|
-
// src/ui/lib/adaptive-resource-budget.ts
|
|
9788
|
-
var scopes = {
|
|
9789
|
-
module: "resource-budget:module",
|
|
9790
|
-
network: "resource-budget:network"
|
|
9791
|
-
};
|
|
9792
|
-
var usefulnessScopes = {
|
|
9793
|
-
module: "resource-usefulness:module",
|
|
9794
|
-
network: "resource-usefulness:network"
|
|
9795
|
-
};
|
|
9796
|
-
var PRELOAD_USE_WINDOW_MS = 1e4;
|
|
9797
|
-
var pendingPreloads = /* @__PURE__ */ new Map();
|
|
9798
|
-
var activeTasks = {
|
|
9799
|
-
module: 0,
|
|
9800
|
-
network: 0
|
|
9801
|
-
};
|
|
9802
|
-
var budgets = {
|
|
9803
|
-
paused: {
|
|
9804
|
-
tier: "paused",
|
|
9805
|
-
allowModulePreload: false,
|
|
9806
|
-
allowNetworkPrefetch: false,
|
|
9807
|
-
maxPrefetchBytes: 0,
|
|
9808
|
-
maxConcurrentModulePreloads: 0,
|
|
9809
|
-
maxConcurrentNetworkPrefetches: 0,
|
|
9810
|
-
reason: "hidden"
|
|
9811
|
-
},
|
|
9812
|
-
constrained: {
|
|
9813
|
-
tier: "constrained",
|
|
9814
|
-
allowModulePreload: false,
|
|
9815
|
-
allowNetworkPrefetch: false,
|
|
9816
|
-
maxPrefetchBytes: 0,
|
|
9817
|
-
maxConcurrentModulePreloads: 0,
|
|
9818
|
-
maxConcurrentNetworkPrefetches: 0,
|
|
9819
|
-
reason: "environment"
|
|
9820
|
-
},
|
|
9821
|
-
balanced: {
|
|
9822
|
-
tier: "balanced",
|
|
9823
|
-
allowModulePreload: true,
|
|
9824
|
-
allowNetworkPrefetch: true,
|
|
9825
|
-
maxPrefetchBytes: 128 * 1024,
|
|
9826
|
-
maxConcurrentModulePreloads: 1,
|
|
9827
|
-
maxConcurrentNetworkPrefetches: 1,
|
|
9828
|
-
reason: "environment"
|
|
9829
|
-
},
|
|
9830
|
-
eager: {
|
|
9831
|
-
tier: "eager",
|
|
9832
|
-
allowModulePreload: true,
|
|
9833
|
-
allowNetworkPrefetch: true,
|
|
9834
|
-
maxPrefetchBytes: 512 * 1024,
|
|
9835
|
-
maxConcurrentModulePreloads: 2,
|
|
9836
|
-
maxConcurrentNetworkPrefetches: 2,
|
|
9837
|
-
reason: "default"
|
|
9838
|
-
}
|
|
9839
|
-
};
|
|
9840
|
-
function withReason(tier, reason) {
|
|
9841
|
-
return { ...budgets[tier], reason };
|
|
9842
|
-
}
|
|
9843
|
-
function feedbackIsPoor(feedback) {
|
|
9844
|
-
if (!feedback || feedback.observations < 4) return false;
|
|
9845
|
-
const failureRate = 1 - feedback.successes / feedback.observations;
|
|
9846
|
-
const abandoned = feedback.cancellations + feedback.fallbacks;
|
|
9847
|
-
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;
|
|
9848
|
-
}
|
|
9849
|
-
function preloadKey(kind, action) {
|
|
9850
|
-
return `${kind}:${action}`;
|
|
9851
|
-
}
|
|
9852
|
-
function flushExpiredPreloads(now = Date.now()) {
|
|
9853
|
-
for (const [key, preload] of pendingPreloads) {
|
|
9854
|
-
if (preload.expiresAt > now) continue;
|
|
9855
|
-
recordLocalAdaptiveOutcome(usefulnessScopes[preload.kind], preload.action, {
|
|
9856
|
-
success: false
|
|
9857
|
-
});
|
|
9858
|
-
pendingPreloads.delete(key);
|
|
9859
|
-
}
|
|
9860
|
-
}
|
|
9861
|
-
function markAdaptiveResourceUsed(kind, action, now = Date.now()) {
|
|
9862
|
-
flushExpiredPreloads(now);
|
|
9863
|
-
const key = preloadKey(kind, action);
|
|
9864
|
-
if (!pendingPreloads.has(key)) return;
|
|
9865
|
-
pendingPreloads.delete(key);
|
|
9866
|
-
recordLocalAdaptiveOutcome(
|
|
9867
|
-
usefulnessScopes[kind],
|
|
9868
|
-
action,
|
|
9869
|
-
{ success: true },
|
|
9870
|
-
now
|
|
9871
|
-
);
|
|
9872
|
-
}
|
|
9873
|
-
function computeAdaptiveResourceBudget(environment, feedback) {
|
|
9874
|
-
if (!environment.visible) return withReason("paused", "hidden");
|
|
9875
|
-
if (environment.saveData || ["slow-2g", "2g", "3g"].includes(environment.effectiveType ?? "")) {
|
|
9876
|
-
return withReason("constrained", "environment");
|
|
9877
|
-
}
|
|
9878
|
-
const limitedDevice = (environment.deviceMemoryGb ?? 8) <= 4 || (environment.hardwareConcurrency ?? 8) <= 4;
|
|
9879
|
-
const baseline = limitedDevice ? "balanced" : "eager";
|
|
9880
|
-
if (!feedbackIsPoor(feedback)) {
|
|
9881
|
-
return withReason(baseline, limitedDevice ? "environment" : "default");
|
|
9882
|
-
}
|
|
9883
|
-
return withReason(
|
|
9884
|
-
baseline === "eager" ? "balanced" : "constrained",
|
|
9885
|
-
"feedback"
|
|
9886
|
-
);
|
|
9887
|
-
}
|
|
9888
|
-
function readEnvironment() {
|
|
9889
|
-
const navigatorLike = typeof navigator === "undefined" ? void 0 : navigator;
|
|
9890
|
-
return {
|
|
9891
|
-
visible: typeof document === "undefined" || document.visibilityState !== "hidden",
|
|
9892
|
-
saveData: navigatorLike?.connection?.saveData,
|
|
9893
|
-
effectiveType: navigatorLike?.connection?.effectiveType,
|
|
9894
|
-
deviceMemoryGb: navigatorLike?.deviceMemory,
|
|
9895
|
-
hardwareConcurrency: navigatorLike?.hardwareConcurrency
|
|
9896
|
-
};
|
|
9897
|
-
}
|
|
9898
|
-
function readFeedback(kind) {
|
|
9899
|
-
flushExpiredPreloads();
|
|
9900
|
-
const stats = Object.values(getLocalAdaptiveStats(scopes[kind]));
|
|
9901
|
-
const usefulness = Object.values(
|
|
9902
|
-
getLocalAdaptiveStats(usefulnessScopes[kind])
|
|
9903
|
-
);
|
|
9904
|
-
const observations = stats.reduce((sum, stat) => sum + stat.observations, 0);
|
|
9905
|
-
const latencySamples = stats.filter(
|
|
9906
|
-
(stat) => stat.latencyEwmaMs !== void 0 && stat.observations > 0
|
|
9907
|
-
);
|
|
9908
|
-
const latencyWeight = latencySamples.reduce(
|
|
9909
|
-
(sum, stat) => sum + stat.observations,
|
|
9910
|
-
0
|
|
9911
|
-
);
|
|
9912
|
-
return {
|
|
9913
|
-
observations,
|
|
9914
|
-
successes: stats.reduce((sum, stat) => sum + stat.successes, 0),
|
|
9915
|
-
cancellations: stats.reduce((sum, stat) => sum + stat.cancellations, 0),
|
|
9916
|
-
fallbacks: stats.reduce((sum, stat) => sum + stat.fallbacks, 0),
|
|
9917
|
-
usefulnessObservations: usefulness.reduce(
|
|
9918
|
-
(sum, stat) => sum + stat.observations,
|
|
9919
|
-
0
|
|
9920
|
-
),
|
|
9921
|
-
usefulPreloads: usefulness.reduce((sum, stat) => sum + stat.successes, 0),
|
|
9922
|
-
...latencyWeight > 0 ? {
|
|
9923
|
-
latencyEwmaMs: latencySamples.reduce(
|
|
9924
|
-
(sum, stat) => sum + (stat.latencyEwmaMs ?? 0) * stat.observations,
|
|
9925
|
-
0
|
|
9926
|
-
) / latencyWeight
|
|
9927
|
-
} : {}
|
|
9928
|
-
};
|
|
9929
|
-
}
|
|
9930
|
-
function getAdaptiveResourceBudget(kind) {
|
|
9931
|
-
return computeAdaptiveResourceBudget(readEnvironment(), readFeedback(kind));
|
|
9932
|
-
}
|
|
9933
|
-
function runAdaptiveBackgroundTask(kind, action, task, options = {}) {
|
|
9934
|
-
const budget = getAdaptiveResourceBudget(kind);
|
|
9935
|
-
const allowed = kind === "module" ? budget.allowModulePreload : budget.allowNetworkPrefetch && (options.estimatedBytes === void 0 || options.estimatedBytes <= budget.maxPrefetchBytes);
|
|
9936
|
-
const concurrency = kind === "module" ? budget.maxConcurrentModulePreloads : budget.maxConcurrentNetworkPrefetches;
|
|
9937
|
-
if (!allowed || activeTasks[kind] >= concurrency) return false;
|
|
9938
|
-
activeTasks[kind] += 1;
|
|
9939
|
-
const key = preloadKey(kind, action);
|
|
9940
|
-
pendingPreloads.set(key, {
|
|
9941
|
-
kind,
|
|
9942
|
-
action,
|
|
9943
|
-
expiresAt: Date.now() + PRELOAD_USE_WINDOW_MS
|
|
9944
|
-
});
|
|
9945
|
-
const startedAt = performance.now();
|
|
9946
|
-
void Promise.resolve().then(task).then(
|
|
9947
|
-
() => {
|
|
9948
|
-
activeTasks[kind] -= 1;
|
|
9949
|
-
recordLocalAdaptiveOutcome(scopes[kind], action, {
|
|
9950
|
-
success: true,
|
|
9951
|
-
latencyMs: performance.now() - startedAt
|
|
9952
|
-
});
|
|
9953
|
-
},
|
|
9954
|
-
() => {
|
|
9955
|
-
activeTasks[kind] -= 1;
|
|
9956
|
-
pendingPreloads.delete(key);
|
|
9957
|
-
recordLocalAdaptiveOutcome(scopes[kind], action, {
|
|
9958
|
-
success: false,
|
|
9959
|
-
latencyMs: performance.now() - startedAt
|
|
9960
|
-
});
|
|
9961
|
-
}
|
|
9962
|
-
);
|
|
9963
|
-
return true;
|
|
9964
|
-
}
|
|
9965
|
-
|
|
9966
|
-
// src/ui/shell/tabUtils.tsx
|
|
9967
|
-
init_define_import_meta_env();
|
|
9968
|
-
import { lazy, memo as memo2, Suspense } from "react";
|
|
9969
|
-
import { useTranslation as useTranslation9 } from "react-i18next";
|
|
9970
|
-
|
|
9971
8960
|
// src/ui/lib/host-to-ssh-host.ts
|
|
9972
8961
|
init_define_import_meta_env();
|
|
9973
8962
|
function hostToSSHHost(h) {
|
|
@@ -10004,446 +8993,7 @@ function hostToSSHHost(h) {
|
|
|
10004
8993
|
};
|
|
10005
8994
|
}
|
|
10006
8995
|
|
|
10007
|
-
// src/ui/shell/CompanionFrame.tsx
|
|
10008
|
-
init_define_import_meta_env();
|
|
10009
|
-
import {
|
|
10010
|
-
memo,
|
|
10011
|
-
useCallback as useCallback9,
|
|
10012
|
-
useEffect as useEffect18,
|
|
10013
|
-
useMemo as useMemo10,
|
|
10014
|
-
useRef as useRef8,
|
|
10015
|
-
useState as useState16
|
|
10016
|
-
} from "react";
|
|
10017
|
-
import { useTranslation as useTranslation8 } from "react-i18next";
|
|
10018
|
-
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
10019
|
-
var DEFAULT_SIDE_SIZE = 360;
|
|
10020
|
-
var DEFAULT_BOTTOM_SIZE = 280;
|
|
10021
|
-
var MIN_SIZE = 200;
|
|
10022
|
-
function DefaultsReader({
|
|
10023
|
-
def,
|
|
10024
|
-
onValue
|
|
10025
|
-
}) {
|
|
10026
|
-
const Reader = def.Defaults;
|
|
10027
|
-
const report = useCallback9(
|
|
10028
|
-
(value) => onValue(def.id, value),
|
|
10029
|
-
[def.id, onValue]
|
|
10030
|
-
);
|
|
10031
|
-
return Reader ? /* @__PURE__ */ jsx13(Reader, { onValue: report }) : null;
|
|
10032
|
-
}
|
|
10033
|
-
function sideIcon(side) {
|
|
10034
|
-
if (side === "left") return ArrowLeftToLine;
|
|
10035
|
-
if (side === "bottom") return ArrowDownToLine;
|
|
10036
|
-
return ArrowRightToLine;
|
|
10037
|
-
}
|
|
10038
|
-
var CompanionFrame = memo(function CompanionFrame2({
|
|
10039
|
-
tab,
|
|
10040
|
-
isVisible,
|
|
10041
|
-
children
|
|
10042
|
-
}) {
|
|
10043
|
-
const defs = useCompanionDefs();
|
|
10044
|
-
const layoutDefs = useCompanionLayoutDefs();
|
|
10045
|
-
const applicable = useMemo10(
|
|
10046
|
-
() => arrangeCompanions(
|
|
10047
|
-
defs.filter((def) => companionApplies(def, tab)),
|
|
10048
|
-
resolveCompanionLayout(tab.type, tab.host).order
|
|
10049
|
-
),
|
|
10050
|
-
// tab.host and tab.type decide it
|
|
10051
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10052
|
-
[defs, layoutDefs, tab.type, tab.host]
|
|
10053
|
-
);
|
|
10054
|
-
if (applicable.length === 0) return /* @__PURE__ */ jsx13(Fragment3, { children });
|
|
10055
|
-
return /* @__PURE__ */ jsx13(CompanionLayout, { tab, defs: applicable, isVisible, children });
|
|
10056
|
-
});
|
|
10057
|
-
function CompanionLayout({
|
|
10058
|
-
tab,
|
|
10059
|
-
defs,
|
|
10060
|
-
isVisible,
|
|
10061
|
-
children
|
|
10062
|
-
}) {
|
|
10063
|
-
const { t } = useTranslation8();
|
|
10064
|
-
const isMobile = useIsMobile();
|
|
10065
|
-
const key = companionKey(tab);
|
|
10066
|
-
const state2 = useCompanionState(key);
|
|
10067
|
-
const [defaults3, setDefaults] = useState16(
|
|
10068
|
-
{}
|
|
10069
|
-
);
|
|
10070
|
-
const [dragging, setDragging] = useState16(false);
|
|
10071
|
-
const [mounted, setMounted] = useState16(/* @__PURE__ */ new Set());
|
|
10072
|
-
const rootRef = useRef8(null);
|
|
10073
|
-
const onDefaults = useCallback9((id, value) => {
|
|
10074
|
-
setDefaults((prev) => {
|
|
10075
|
-
const old = prev[id];
|
|
10076
|
-
if (old && old.open === value.open && old.side === value.side && old.size === value.size && old.edgeButton === value.edgeButton) {
|
|
10077
|
-
return prev;
|
|
10078
|
-
}
|
|
10079
|
-
return { ...prev, [id]: value };
|
|
10080
|
-
});
|
|
10081
|
-
}, []);
|
|
10082
|
-
useEffect18(() => {
|
|
10083
|
-
if (state2.seen || !isVisible) return;
|
|
10084
|
-
const ready = defs.every(
|
|
10085
|
-
(def) => !def.Defaults || defaults3[def.id] !== void 0
|
|
10086
|
-
);
|
|
10087
|
-
if (!ready) return;
|
|
10088
|
-
const auto = defs.find((def) => defaults3[def.id]?.open);
|
|
10089
|
-
patchCompanionState(key, { seen: true, openId: auto?.id ?? null });
|
|
10090
|
-
}, [state2.seen, isVisible, defs, defaults3, key]);
|
|
10091
|
-
const active = defs.find((def) => def.id === state2.openId) ?? null;
|
|
10092
|
-
useEffect18(() => {
|
|
10093
|
-
if (!active) return;
|
|
10094
|
-
setMounted(
|
|
10095
|
-
(prev) => prev.has(active.id) ? prev : new Set(prev).add(active.id)
|
|
10096
|
-
);
|
|
10097
|
-
}, [active]);
|
|
10098
|
-
const activeDefaults = active ? defaults3[active.id] : void 0;
|
|
10099
|
-
const layout = useMemo10(
|
|
10100
|
-
() => resolveCompanionLayout(tab.type, tab.host),
|
|
10101
|
-
[tab.type, tab.host]
|
|
10102
|
-
);
|
|
10103
|
-
const side = isMobile ? "bottom" : state2.side ?? layout.side ?? activeDefaults?.side ?? "right";
|
|
10104
|
-
const baseSize = state2.size ?? activeDefaults?.size ?? (side === "bottom" ? DEFAULT_BOTTOM_SIZE : DEFAULT_SIDE_SIZE);
|
|
10105
|
-
const setSide = useCallback9(
|
|
10106
|
-
(next) => patchCompanionState(key, { side: next }),
|
|
10107
|
-
[key]
|
|
10108
|
-
);
|
|
10109
|
-
const close = useCallback9(
|
|
10110
|
-
() => patchCompanionState(key, { openId: null }),
|
|
10111
|
-
[key]
|
|
10112
|
-
);
|
|
10113
|
-
const startResize = (event) => {
|
|
10114
|
-
event.preventDefault();
|
|
10115
|
-
const root = rootRef.current;
|
|
10116
|
-
if (!root) return;
|
|
10117
|
-
const rect = root.getBoundingClientRect();
|
|
10118
|
-
const total = side === "bottom" ? rect.height : rect.width;
|
|
10119
|
-
const max = Math.max(MIN_SIZE, total - MIN_SIZE);
|
|
10120
|
-
setDragging(true);
|
|
10121
|
-
const move = (e) => {
|
|
10122
|
-
const raw = side === "right" ? rect.right - e.clientX : side === "left" ? e.clientX - rect.left : rect.bottom - e.clientY;
|
|
10123
|
-
patchCompanionState(key, {
|
|
10124
|
-
size: Math.round(Math.min(max, Math.max(MIN_SIZE, raw)))
|
|
10125
|
-
});
|
|
10126
|
-
};
|
|
10127
|
-
const up = () => {
|
|
10128
|
-
setDragging(false);
|
|
10129
|
-
window.removeEventListener("mousemove", move);
|
|
10130
|
-
window.removeEventListener("mouseup", up);
|
|
10131
|
-
};
|
|
10132
|
-
window.addEventListener("mousemove", move);
|
|
10133
|
-
window.addEventListener("mouseup", up);
|
|
10134
|
-
};
|
|
10135
|
-
const getHandle = useCallback9(
|
|
10136
|
-
() => tab.terminalRef?.current ?? null,
|
|
10137
|
-
[tab.terminalRef]
|
|
10138
|
-
);
|
|
10139
|
-
const sshHost = useMemo10(
|
|
10140
|
-
() => tab.host ? hostToSSHHost(tab.host) : void 0,
|
|
10141
|
-
[tab.host]
|
|
10142
|
-
);
|
|
10143
|
-
const showEdge = defs.filter((def) => defaults3[def.id]?.edgeButton !== false);
|
|
10144
|
-
const vertical = side === "bottom";
|
|
10145
|
-
const clamped = vertical ? Math.min(baseSize, 2e3) : baseSize;
|
|
10146
|
-
const paneStyle = isMobile ? { height: "55%" } : vertical ? { height: clamped } : { width: clamped };
|
|
10147
|
-
const SideIcon = sideIcon(side);
|
|
10148
|
-
return /* @__PURE__ */ jsxs6("div", { className: "flex h-full w-full min-h-0 min-w-0", children: [
|
|
10149
|
-
defs.map(
|
|
10150
|
-
(def) => def.Defaults ? /* @__PURE__ */ jsx13(DefaultsReader, { def, onValue: onDefaults }, def.id) : null
|
|
10151
|
-
),
|
|
10152
|
-
/* @__PURE__ */ jsxs6(
|
|
10153
|
-
"div",
|
|
10154
|
-
{
|
|
10155
|
-
ref: rootRef,
|
|
10156
|
-
className: cn(
|
|
10157
|
-
"relative flex flex-1 min-h-0 min-w-0",
|
|
10158
|
-
vertical ? "flex-col" : side === "left" ? "flex-row-reverse" : "flex-row"
|
|
10159
|
-
),
|
|
10160
|
-
children: [
|
|
10161
|
-
/* @__PURE__ */ jsx13("div", { className: "relative flex-1 min-h-0 min-w-0", children }),
|
|
10162
|
-
defs.map((def) => {
|
|
10163
|
-
if (!mounted.has(def.id)) return null;
|
|
10164
|
-
const open = active?.id === def.id;
|
|
10165
|
-
const Component = def.component;
|
|
10166
|
-
const Icon = def.icon;
|
|
10167
|
-
return /* @__PURE__ */ jsxs6(
|
|
10168
|
-
"div",
|
|
10169
|
-
{
|
|
10170
|
-
className: cn(
|
|
10171
|
-
"relative flex-shrink-0 flex-col min-h-0 min-w-0 bg-background border-border",
|
|
10172
|
-
open ? "flex" : "hidden",
|
|
10173
|
-
vertical ? "border-t" : side === "left" ? "border-r" : "border-l",
|
|
10174
|
-
isMobile && "absolute inset-x-0 bottom-0 z-20 shadow-lg"
|
|
10175
|
-
),
|
|
10176
|
-
style: paneStyle,
|
|
10177
|
-
children: [
|
|
10178
|
-
!isMobile && /* @__PURE__ */ jsx13(
|
|
10179
|
-
"div",
|
|
10180
|
-
{
|
|
10181
|
-
role: "separator",
|
|
10182
|
-
"aria-label": t("companion.resize"),
|
|
10183
|
-
onMouseDown: startResize,
|
|
10184
|
-
className: cn(
|
|
10185
|
-
"absolute z-10",
|
|
10186
|
-
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",
|
|
10187
|
-
dragging && "bg-primary/30"
|
|
10188
|
-
)
|
|
10189
|
-
}
|
|
10190
|
-
),
|
|
10191
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5 h-8 px-2 border-b border-border flex-shrink-0", children: [
|
|
10192
|
-
Icon && /* @__PURE__ */ jsx13(Icon, { className: "size-3.5 text-muted-foreground" }),
|
|
10193
|
-
/* @__PURE__ */ jsx13("span", { className: "text-xs font-medium truncate flex-1", children: def.titleKey ? t(def.titleKey) : def.id }),
|
|
10194
|
-
!isMobile && /* @__PURE__ */ jsx13(
|
|
10195
|
-
"button",
|
|
10196
|
-
{
|
|
10197
|
-
type: "button",
|
|
10198
|
-
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10199
|
-
title: t("companion.moveSide"),
|
|
10200
|
-
onClick: () => setSide(
|
|
10201
|
-
side === "right" ? "bottom" : side === "bottom" ? "left" : "right"
|
|
10202
|
-
),
|
|
10203
|
-
children: /* @__PURE__ */ jsx13(SideIcon, { className: "size-3.5" })
|
|
10204
|
-
}
|
|
10205
|
-
),
|
|
10206
|
-
/* @__PURE__ */ jsx13(
|
|
10207
|
-
"button",
|
|
10208
|
-
{
|
|
10209
|
-
type: "button",
|
|
10210
|
-
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10211
|
-
title: t("companion.close"),
|
|
10212
|
-
onClick: close,
|
|
10213
|
-
children: /* @__PURE__ */ jsx13(X, { className: "size-3.5" })
|
|
10214
|
-
}
|
|
10215
|
-
)
|
|
10216
|
-
] }),
|
|
10217
|
-
/* @__PURE__ */ jsx13("div", { className: "flex-1 min-h-0 min-w-0 overflow-hidden", children: /* @__PURE__ */ jsx13(
|
|
10218
|
-
Component,
|
|
10219
|
-
{
|
|
10220
|
-
tab,
|
|
10221
|
-
host: tab.host,
|
|
10222
|
-
sshHost,
|
|
10223
|
-
getHandle,
|
|
10224
|
-
side,
|
|
10225
|
-
isVisible: isVisible && open,
|
|
10226
|
-
close,
|
|
10227
|
-
setSide
|
|
10228
|
-
}
|
|
10229
|
-
) })
|
|
10230
|
-
]
|
|
10231
|
-
},
|
|
10232
|
-
def.id
|
|
10233
|
-
);
|
|
10234
|
-
})
|
|
10235
|
-
]
|
|
10236
|
-
}
|
|
10237
|
-
),
|
|
10238
|
-
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) => {
|
|
10239
|
-
const Icon = def.icon ?? PanelRight;
|
|
10240
|
-
const open = active?.id === def.id;
|
|
10241
|
-
return /* @__PURE__ */ jsx13(
|
|
10242
|
-
"button",
|
|
10243
|
-
{
|
|
10244
|
-
type: "button",
|
|
10245
|
-
title: def.titleKey ? t(def.titleKey) : def.id,
|
|
10246
|
-
"aria-pressed": open,
|
|
10247
|
-
onClick: () => patchCompanionState(key, {
|
|
10248
|
-
seen: true,
|
|
10249
|
-
openId: open ? null : def.id
|
|
10250
|
-
}),
|
|
10251
|
-
className: cn(
|
|
10252
|
-
"p-1 text-muted-foreground hover:text-foreground",
|
|
10253
|
-
open && "text-foreground bg-accent"
|
|
10254
|
-
),
|
|
10255
|
-
children: /* @__PURE__ */ jsx13(Icon, { className: "size-3.5" })
|
|
10256
|
-
},
|
|
10257
|
-
def.id
|
|
10258
|
-
);
|
|
10259
|
-
}) })
|
|
10260
|
-
] });
|
|
10261
|
-
}
|
|
10262
|
-
|
|
10263
|
-
// src/ui/shell/tabUtils.tsx
|
|
10264
|
-
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
10265
|
-
var PluginsTab = lazy(
|
|
10266
|
-
() => import("./PluginsTab-ZSMTJ5C5.js").then((m) => ({ default: m.PluginsTab }))
|
|
10267
|
-
);
|
|
10268
|
-
function preloadTabSurface(type) {
|
|
10269
|
-
const loader = getTabType(type)?.preload;
|
|
10270
|
-
if (loader) runAdaptiveBackgroundTask("module", `tab:${type}`, loader);
|
|
10271
|
-
}
|
|
10272
|
-
function markTabSurfaceUsed(type) {
|
|
10273
|
-
markAdaptiveResourceUsed("module", `tab:${type}`);
|
|
10274
|
-
}
|
|
10275
|
-
function EmptyState({
|
|
10276
|
-
icon: Icon,
|
|
10277
|
-
messageKey
|
|
10278
|
-
}) {
|
|
10279
|
-
const { t } = useTranslation9();
|
|
10280
|
-
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center flex-1 gap-3 p-6 text-center", children: [
|
|
10281
|
-
/* @__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" }) }),
|
|
10282
|
-
/* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-muted-foreground/60", children: t(messageKey) })
|
|
10283
|
-
] });
|
|
10284
|
-
}
|
|
10285
|
-
function TabChunkFallback() {
|
|
10286
|
-
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" }) });
|
|
10287
|
-
}
|
|
10288
|
-
function withTabSuspense(node) {
|
|
10289
|
-
return /* @__PURE__ */ jsx14(Suspense, { fallback: /* @__PURE__ */ jsx14(TabChunkFallback, {}), children: node });
|
|
10290
|
-
}
|
|
10291
|
-
function PanelTabFrame({ children }) {
|
|
10292
|
-
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 }) });
|
|
10293
|
-
}
|
|
10294
|
-
function tabIcon(type) {
|
|
10295
|
-
switch (type) {
|
|
10296
|
-
case "user-profile":
|
|
10297
|
-
case "admin-settings":
|
|
10298
|
-
return /* @__PURE__ */ jsx14(Settings, { className: "size-3.5" });
|
|
10299
|
-
case "split-screen":
|
|
10300
|
-
return /* @__PURE__ */ jsx14(LayoutPanelLeft, { className: "size-3.5" });
|
|
10301
|
-
case "plugins":
|
|
10302
|
-
return /* @__PURE__ */ jsx14(Puzzle, { className: "size-3.5" });
|
|
10303
|
-
default: {
|
|
10304
|
-
const Icon = getTabType(type)?.icon;
|
|
10305
|
-
return Icon ? /* @__PURE__ */ jsx14(Icon, { className: "size-3.5" }) : null;
|
|
10306
|
-
}
|
|
10307
|
-
}
|
|
10308
|
-
}
|
|
10309
|
-
var RegisteredTab = memo2(function RegisteredTab2({
|
|
10310
|
-
def,
|
|
10311
|
-
tab,
|
|
10312
|
-
isVisible,
|
|
10313
|
-
isFocusedPane,
|
|
10314
|
-
inSplit,
|
|
10315
|
-
shell: shell2
|
|
10316
|
-
}) {
|
|
10317
|
-
const { host, label } = tab;
|
|
10318
|
-
if (def.requiresHost && !host) {
|
|
10319
|
-
return /* @__PURE__ */ jsx14(
|
|
10320
|
-
EmptyState,
|
|
10321
|
-
{
|
|
10322
|
-
icon: Server,
|
|
10323
|
-
messageKey: def.noHostMessageKey ?? "hosts.noHostSelected"
|
|
10324
|
-
}
|
|
10325
|
-
);
|
|
10326
|
-
}
|
|
10327
|
-
const Component = def.component;
|
|
10328
|
-
const content = /* @__PURE__ */ jsx14(
|
|
10329
|
-
Component,
|
|
10330
|
-
{
|
|
10331
|
-
tab,
|
|
10332
|
-
host,
|
|
10333
|
-
sshHost: host ? hostToSSHHost(host) : void 0,
|
|
10334
|
-
label,
|
|
10335
|
-
isVisible,
|
|
10336
|
-
isFocusedPane,
|
|
10337
|
-
inSplit,
|
|
10338
|
-
handleRef: trackTabHandle(
|
|
10339
|
-
tab.terminalRef
|
|
10340
|
-
),
|
|
10341
|
-
shell: shell2
|
|
10342
|
-
}
|
|
10343
|
-
);
|
|
10344
|
-
return withTabSuspense(
|
|
10345
|
-
/* @__PURE__ */ jsx14(CompanionFrame, { tab, isVisible, children: def.panelFrame ? /* @__PURE__ */ jsx14(PanelTabFrame, { children: content }) : content })
|
|
10346
|
-
);
|
|
10347
|
-
});
|
|
10348
|
-
var PanelAsTab = memo2(function PanelAsTab2({
|
|
10349
|
-
panel,
|
|
10350
|
-
isVisible,
|
|
10351
|
-
targetTab,
|
|
10352
|
-
shell: shell2
|
|
10353
|
-
}) {
|
|
10354
|
-
const Panel = panel.component;
|
|
10355
|
-
return withTabSuspense(
|
|
10356
|
-
/* @__PURE__ */ jsx14(PanelTabFrame, { children: /* @__PURE__ */ jsx14(
|
|
10357
|
-
Panel,
|
|
10358
|
-
{
|
|
10359
|
-
targetTab,
|
|
10360
|
-
active: isVisible,
|
|
10361
|
-
shell: shell2,
|
|
10362
|
-
setEditing: noop,
|
|
10363
|
-
placement: "tab"
|
|
10364
|
-
}
|
|
10365
|
-
) })
|
|
10366
|
-
);
|
|
10367
|
-
});
|
|
10368
|
-
function noop() {
|
|
10369
|
-
}
|
|
10370
|
-
function renderTabContent(tab, context) {
|
|
10371
|
-
const {
|
|
10372
|
-
shell: shell2,
|
|
10373
|
-
isVisible = true,
|
|
10374
|
-
isFocusedPane = true,
|
|
10375
|
-
inSplit = false
|
|
10376
|
-
} = context;
|
|
10377
|
-
switch (tab.type) {
|
|
10378
|
-
case "split-screen":
|
|
10379
|
-
return null;
|
|
10380
|
-
case "plugins":
|
|
10381
|
-
return withTabSuspense(/* @__PURE__ */ jsx14(PluginsTab, {}));
|
|
10382
|
-
case "user-profile":
|
|
10383
|
-
case "admin-settings":
|
|
10384
|
-
return null;
|
|
10385
|
-
default: {
|
|
10386
|
-
const def = getTabType(tab.type);
|
|
10387
|
-
if (!def && tab.type === "dashboard") return null;
|
|
10388
|
-
if (!def) {
|
|
10389
|
-
const panel = getPanel(tab.type);
|
|
10390
|
-
if (panel) {
|
|
10391
|
-
return /* @__PURE__ */ jsx14(
|
|
10392
|
-
PanelAsTab,
|
|
10393
|
-
{
|
|
10394
|
-
panel,
|
|
10395
|
-
isVisible,
|
|
10396
|
-
targetTab: context.panelTargetTab,
|
|
10397
|
-
shell: shell2
|
|
10398
|
-
}
|
|
10399
|
-
);
|
|
10400
|
-
}
|
|
10401
|
-
return /* @__PURE__ */ jsx14(PluginViewPlaceholder, { kind: "tab", viewId: tab.type });
|
|
10402
|
-
}
|
|
10403
|
-
return /* @__PURE__ */ jsx14(
|
|
10404
|
-
RegisteredTab,
|
|
10405
|
-
{
|
|
10406
|
-
def,
|
|
10407
|
-
tab,
|
|
10408
|
-
isVisible,
|
|
10409
|
-
isFocusedPane,
|
|
10410
|
-
inSplit,
|
|
10411
|
-
shell: shell2
|
|
10412
|
-
}
|
|
10413
|
-
);
|
|
10414
|
-
}
|
|
10415
|
-
}
|
|
10416
|
-
}
|
|
10417
|
-
|
|
10418
|
-
// src/ui/lib/local-adaptive-preferences.ts
|
|
10419
|
-
init_define_import_meta_env();
|
|
10420
|
-
var LOCAL_ADAPTIVE_PREFERENCES_KEY = LOCAL_ADAPTIVE_ENGINE_KEY;
|
|
10421
|
-
function recordLocalPreference(scope, action, now = Date.now()) {
|
|
10422
|
-
recordLocalAdaptiveChoice(scope, action, now);
|
|
10423
|
-
}
|
|
10424
|
-
function getLocalPreference(scope, candidates, fallback, now = Date.now()) {
|
|
10425
|
-
return chooseLocalAdaptiveAction({
|
|
10426
|
-
scope,
|
|
10427
|
-
candidates,
|
|
10428
|
-
fallback,
|
|
10429
|
-
now
|
|
10430
|
-
}).action;
|
|
10431
|
-
}
|
|
10432
|
-
function clearLocalAdaptivePreferences() {
|
|
10433
|
-
clearLocalAdaptiveEngine();
|
|
10434
|
-
}
|
|
10435
|
-
var hostActionScope = (hostId) => `host-action:${hostId}`;
|
|
10436
|
-
function recordHostActionPreference(hostId, action) {
|
|
10437
|
-
recordLocalPreference(hostActionScope(hostId), action);
|
|
10438
|
-
}
|
|
10439
|
-
function getPreferredHostAction(hostId, candidates, fallback) {
|
|
10440
|
-
return getLocalPreference(hostActionScope(hostId), candidates, fallback);
|
|
10441
|
-
}
|
|
10442
|
-
|
|
10443
8996
|
export {
|
|
10444
|
-
Checkbox2 as Checkbox,
|
|
10445
|
-
PasswordInput,
|
|
10446
|
-
Textarea,
|
|
10447
8997
|
rem,
|
|
10448
8998
|
remScale,
|
|
10449
8999
|
useIsMobile,
|
|
@@ -10482,6 +9032,14 @@ export {
|
|
|
10482
9032
|
isCoreRailView,
|
|
10483
9033
|
railItemLabel,
|
|
10484
9034
|
resetRegisteredRailItems,
|
|
9035
|
+
useCompanionDefs,
|
|
9036
|
+
useCompanionLayoutDefs,
|
|
9037
|
+
resolveCompanionLayout,
|
|
9038
|
+
companionApplies,
|
|
9039
|
+
arrangeCompanions,
|
|
9040
|
+
companionKey,
|
|
9041
|
+
patchCompanionState,
|
|
9042
|
+
useCompanionState,
|
|
10485
9043
|
registerHostEditorSection,
|
|
10486
9044
|
unregisterHostEditorSection,
|
|
10487
9045
|
getHostEditorSection,
|
|
@@ -10535,8 +9093,10 @@ export {
|
|
|
10535
9093
|
listExtensions,
|
|
10536
9094
|
getSettingsComponent,
|
|
10537
9095
|
listSettingsComponents,
|
|
9096
|
+
useSettingsComponents,
|
|
10538
9097
|
registerAction,
|
|
10539
9098
|
listActions,
|
|
9099
|
+
invokeAction,
|
|
10540
9100
|
declareActionSlot,
|
|
10541
9101
|
registerSlotContribution,
|
|
10542
9102
|
getSlotContributions,
|
|
@@ -10621,25 +9181,5 @@ export {
|
|
|
10621
9181
|
useLayouts,
|
|
10622
9182
|
layoutLabel,
|
|
10623
9183
|
createPluginApp,
|
|
10624
|
-
|
|
10625
|
-
SettingsFieldRow,
|
|
10626
|
-
usePluginHostSections,
|
|
10627
|
-
HostPluginSections,
|
|
10628
|
-
HostFeatureFields,
|
|
10629
|
-
ActionSlot,
|
|
10630
|
-
ComponentSlot,
|
|
10631
|
-
trackTabHandle,
|
|
10632
|
-
useTabHandlesVersion,
|
|
10633
|
-
PluginViewPlaceholder,
|
|
10634
|
-
markAdaptiveResourceUsed,
|
|
10635
|
-
getAdaptiveResourceBudget,
|
|
10636
|
-
runAdaptiveBackgroundTask,
|
|
10637
|
-
preloadTabSurface,
|
|
10638
|
-
markTabSurfaceUsed,
|
|
10639
|
-
tabIcon,
|
|
10640
|
-
renderTabContent,
|
|
10641
|
-
LOCAL_ADAPTIVE_PREFERENCES_KEY,
|
|
10642
|
-
clearLocalAdaptivePreferences,
|
|
10643
|
-
recordHostActionPreference,
|
|
10644
|
-
getPreferredHostAction
|
|
9184
|
+
hostToSSHHost
|
|
10645
9185
|
};
|