@ddtcorex/dsh-maestro-config 0.1.1 → 0.2.0
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/lib/client.js +825 -445
- package/lib/index.d.ts +24 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +8 -1
- package/lib/index.js.map +1 -1
- package/lib/types/client/MaestroSettings.d.ts +25 -0
- package/lib/types/client/MaestroSettings.d.ts.map +1 -0
- package/lib/types/client/Settings.d.ts +11 -0
- package/lib/types/client/Settings.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/maestro-card.d.ts.map +1 -1
- package/package.json +4 -6
- package/src/client/MaestroSettings.tsx +1463 -0
- package/src/client/index.tsx +10 -7
- package/src/client/maestro-card.jsx +225 -21
- package/src/host/index.ts +12 -3
package/lib/client.js
CHANGED
|
@@ -15,8 +15,8 @@ var __commonJS = (cb, mod) => function __require() {
|
|
|
15
15
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
16
|
};
|
|
17
17
|
var __export = (target, all) => {
|
|
18
|
-
for (var
|
|
19
|
-
__defProp(target,
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
20
|
};
|
|
21
21
|
var __copyProps = (to, from, except, desc) => {
|
|
22
22
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -1366,16 +1366,16 @@ var require_dijkstra = __commonJS({
|
|
|
1366
1366
|
*/
|
|
1367
1367
|
PriorityQueue: {
|
|
1368
1368
|
make: function(opts) {
|
|
1369
|
-
var T = dijkstra.PriorityQueue,
|
|
1369
|
+
var T = dijkstra.PriorityQueue, t2 = {}, key;
|
|
1370
1370
|
opts = opts || {};
|
|
1371
1371
|
for (key in T) {
|
|
1372
1372
|
if (T.hasOwnProperty(key)) {
|
|
1373
|
-
|
|
1373
|
+
t2[key] = T[key];
|
|
1374
1374
|
}
|
|
1375
1375
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
return
|
|
1376
|
+
t2.queue = [];
|
|
1377
|
+
t2.sorter = opts.sorter || T.default_sorter;
|
|
1378
|
+
return t2;
|
|
1379
1379
|
},
|
|
1380
1380
|
default_sorter: function(a, b) {
|
|
1381
1381
|
return a.cost - b.cost;
|
|
@@ -2117,11 +2117,12 @@ var require_browser = __commonJS({
|
|
|
2117
2117
|
// src/client/index.tsx
|
|
2118
2118
|
var index_exports = {};
|
|
2119
2119
|
__export(index_exports, {
|
|
2120
|
-
apply: () => apply
|
|
2120
|
+
apply: () => apply,
|
|
2121
|
+
inject: () => inject
|
|
2121
2122
|
});
|
|
2122
2123
|
module.exports = __toCommonJS(index_exports);
|
|
2123
2124
|
|
|
2124
|
-
// src/client/
|
|
2125
|
+
// src/client/MaestroSettings.tsx
|
|
2125
2126
|
var import_react = require("react");
|
|
2126
2127
|
var import_qrcode = __toESM(require_browser(), 1);
|
|
2127
2128
|
|
|
@@ -2155,72 +2156,252 @@ function gitlabWebhookUrl(hostname) {
|
|
|
2155
2156
|
return `https://${authority}/hooks/gitlab-mr`;
|
|
2156
2157
|
}
|
|
2157
2158
|
|
|
2158
|
-
// src/client/
|
|
2159
|
-
var
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2159
|
+
// src/client/MaestroSettings.tsx
|
|
2160
|
+
var t = {
|
|
2161
|
+
bgLayer1: "var(--dsw-alias-bg-layer-1)",
|
|
2162
|
+
bgLayer2: "var(--dsw-alias-bg-layer-2)",
|
|
2163
|
+
bgLayer3: "var(--dsw-alias-bg-layer-3)",
|
|
2164
|
+
borderL2: "var(--dsw-alias-border-l2)",
|
|
2165
|
+
labelPrimary: "var(--dsw-alias-label-primary)",
|
|
2166
|
+
labelSecondary: "var(--dsw-alias-label-secondary)",
|
|
2167
|
+
labelTertiary: "var(--dsw-alias-label-tertiary)",
|
|
2168
|
+
labelDimmed: "var(--dsw-alias-label-dimmed)",
|
|
2169
|
+
labelFg: "var(--dsw-alias-label-primary-foreground)",
|
|
2170
|
+
primaryFill: "var(--dsw-alias-button-primary-fill)",
|
|
2171
|
+
primaryHover: "var(--dsw-alias-button-primary-hover)",
|
|
2172
|
+
interactiveHover: "var(--dsw-alias-interactive-bg-hover)",
|
|
2173
|
+
interactiveActive: "var(--dsw-alias-interactive-bg-active)",
|
|
2174
|
+
stateError: "var(--dsw-alias-state-error-primary)",
|
|
2175
|
+
brand: "var(--dsw-alias-brand-primary)",
|
|
2176
|
+
shadowLv3: "var(--dsw-shadow-lv3)",
|
|
2177
|
+
scrollbarL2: "var(--dsw-alias-scrollbar-bg-l2)"
|
|
2170
2178
|
};
|
|
2179
|
+
function Button({
|
|
2180
|
+
variant = "ghost",
|
|
2181
|
+
size = "md",
|
|
2182
|
+
icon,
|
|
2183
|
+
children,
|
|
2184
|
+
style,
|
|
2185
|
+
...rest
|
|
2186
|
+
}) {
|
|
2187
|
+
const base = {
|
|
2188
|
+
display: "inline-flex",
|
|
2189
|
+
alignItems: "center",
|
|
2190
|
+
justifyContent: "center",
|
|
2191
|
+
gap: 4,
|
|
2192
|
+
border: "none",
|
|
2193
|
+
borderRadius: size === "sm" ? 16 : 18,
|
|
2194
|
+
cursor: "pointer",
|
|
2195
|
+
fontSize: size === "sm" ? 13 : 14,
|
|
2196
|
+
lineHeight: size === "sm" ? "18px" : "22px",
|
|
2197
|
+
padding: size === "sm" ? "0 12px" : "0 14px",
|
|
2198
|
+
height: size === "sm" ? 32 : 36,
|
|
2199
|
+
color: t.labelPrimary,
|
|
2200
|
+
background: "transparent",
|
|
2201
|
+
fontFamily: "inherit"
|
|
2202
|
+
};
|
|
2203
|
+
if (variant === "primary") {
|
|
2204
|
+
base.background = t.primaryFill;
|
|
2205
|
+
base.color = t.labelFg;
|
|
2206
|
+
}
|
|
2207
|
+
if (variant === "outline") {
|
|
2208
|
+
base.border = `1px solid ${t.borderL2}`;
|
|
2209
|
+
base.background = "transparent";
|
|
2210
|
+
}
|
|
2211
|
+
const merged = { ...base, ...style };
|
|
2212
|
+
return (0, import_react.createElement)(
|
|
2213
|
+
"button",
|
|
2214
|
+
{
|
|
2215
|
+
type: "button",
|
|
2216
|
+
style: merged,
|
|
2217
|
+
onMouseEnter: (e) => {
|
|
2218
|
+
if (rest.disabled) return;
|
|
2219
|
+
if (variant === "primary") e.currentTarget.style.background = t.primaryHover;
|
|
2220
|
+
else e.currentTarget.style.background = t.interactiveHover;
|
|
2221
|
+
},
|
|
2222
|
+
onMouseLeave: (e) => {
|
|
2223
|
+
if (variant === "primary") e.currentTarget.style.background = t.primaryFill;
|
|
2224
|
+
else e.currentTarget.style.background = variant === "outline" ? "transparent" : "transparent";
|
|
2225
|
+
},
|
|
2226
|
+
...rest
|
|
2227
|
+
},
|
|
2228
|
+
icon ? (0, import_react.createElement)("span", { style: { display: "inline-flex", width: 16, height: 16, alignItems: "center", justifyContent: "center" } }, icon) : null,
|
|
2229
|
+
children
|
|
2230
|
+
);
|
|
2231
|
+
}
|
|
2232
|
+
function InputWrap({
|
|
2233
|
+
icon,
|
|
2234
|
+
children,
|
|
2235
|
+
style,
|
|
2236
|
+
focused
|
|
2237
|
+
}) {
|
|
2238
|
+
return (0, import_react.createElement)(
|
|
2239
|
+
"span",
|
|
2240
|
+
{
|
|
2241
|
+
style: {
|
|
2242
|
+
display: "inline-flex",
|
|
2243
|
+
alignItems: "center",
|
|
2244
|
+
gap: 8,
|
|
2245
|
+
height: 36,
|
|
2246
|
+
padding: "0 12px",
|
|
2247
|
+
border: `1px solid ${focused ? t.brand : t.borderL2}`,
|
|
2248
|
+
borderRadius: 10,
|
|
2249
|
+
background: t.bgLayer1,
|
|
2250
|
+
flex: 1,
|
|
2251
|
+
minWidth: 0,
|
|
2252
|
+
boxSizing: "border-box",
|
|
2253
|
+
...style
|
|
2254
|
+
}
|
|
2255
|
+
},
|
|
2256
|
+
icon ? (0, import_react.createElement)("span", { style: { display: "inline-flex", width: 16, height: 16, color: t.labelTertiary } }, icon) : null,
|
|
2257
|
+
children
|
|
2258
|
+
);
|
|
2259
|
+
}
|
|
2260
|
+
function FieldInput(props) {
|
|
2261
|
+
const [focused, setFocused] = (0, import_react.useState)(false);
|
|
2262
|
+
const { icon, style, ...rest } = props;
|
|
2263
|
+
return (0, import_react.createElement)(
|
|
2264
|
+
InputWrap,
|
|
2265
|
+
{ icon, focused, style: { ...style, flex: "1 1 auto" } },
|
|
2266
|
+
(0, import_react.createElement)("input", {
|
|
2267
|
+
...rest,
|
|
2268
|
+
onFocus: (e) => {
|
|
2269
|
+
setFocused(true);
|
|
2270
|
+
rest.onFocus?.(e);
|
|
2271
|
+
},
|
|
2272
|
+
onBlur: (e) => {
|
|
2273
|
+
setFocused(false);
|
|
2274
|
+
rest.onBlur?.(e);
|
|
2275
|
+
},
|
|
2276
|
+
style: {
|
|
2277
|
+
flex: 1,
|
|
2278
|
+
minWidth: 0,
|
|
2279
|
+
border: "none",
|
|
2280
|
+
outline: "none",
|
|
2281
|
+
background: "transparent",
|
|
2282
|
+
fontSize: 14,
|
|
2283
|
+
lineHeight: "22px",
|
|
2284
|
+
color: t.labelPrimary,
|
|
2285
|
+
fontFamily: "inherit"
|
|
2286
|
+
}
|
|
2287
|
+
})
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
function TextareaField(props) {
|
|
2291
|
+
const [focused, setFocused] = (0, import_react.useState)(false);
|
|
2292
|
+
return (0, import_react.createElement)("textarea", {
|
|
2293
|
+
...props,
|
|
2294
|
+
onFocus: (e) => {
|
|
2295
|
+
setFocused(true);
|
|
2296
|
+
props.onFocus?.(e);
|
|
2297
|
+
},
|
|
2298
|
+
onBlur: (e) => {
|
|
2299
|
+
setFocused(false);
|
|
2300
|
+
props.onBlur?.(e);
|
|
2301
|
+
},
|
|
2302
|
+
style: {
|
|
2303
|
+
width: "100%",
|
|
2304
|
+
minHeight: 96,
|
|
2305
|
+
padding: "8px 10px",
|
|
2306
|
+
border: `1px solid ${focused ? t.brand : t.borderL2}`,
|
|
2307
|
+
borderRadius: 8,
|
|
2308
|
+
background: t.bgLayer1,
|
|
2309
|
+
color: t.labelPrimary,
|
|
2310
|
+
fontFamily: "inherit",
|
|
2311
|
+
fontSize: 13,
|
|
2312
|
+
lineHeight: "18px",
|
|
2313
|
+
resize: "vertical",
|
|
2314
|
+
boxSizing: "border-box",
|
|
2315
|
+
outline: "none",
|
|
2316
|
+
...props.style
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2171
2320
|
var fieldLabelStyle = {
|
|
2172
|
-
display: "
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2321
|
+
display: "flex",
|
|
2322
|
+
flexDirection: "column",
|
|
2323
|
+
gap: "6px",
|
|
2324
|
+
fontSize: "12px",
|
|
2325
|
+
lineHeight: "16px",
|
|
2326
|
+
fontWeight: "500",
|
|
2327
|
+
color: t.labelSecondary,
|
|
2328
|
+
margin: "12px 0 0"
|
|
2177
2329
|
};
|
|
2178
|
-
var
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
background: "transparent",
|
|
2184
|
-
color: "var(--dsw-alias-label-primary)",
|
|
2185
|
-
font: "inherit",
|
|
2186
|
-
fontSize: 13,
|
|
2187
|
-
cursor: "pointer",
|
|
2188
|
-
flex: "none"
|
|
2330
|
+
var captionStyle = {
|
|
2331
|
+
fontSize: "12px",
|
|
2332
|
+
lineHeight: "16px",
|
|
2333
|
+
color: t.labelSecondary,
|
|
2334
|
+
margin: "4px 0"
|
|
2189
2335
|
};
|
|
2190
|
-
var
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2336
|
+
var cardInsetStyle = {
|
|
2337
|
+
display: "flex",
|
|
2338
|
+
flexDirection: "column",
|
|
2339
|
+
gap: "8px",
|
|
2340
|
+
padding: "12px",
|
|
2341
|
+
borderRadius: "12px",
|
|
2342
|
+
border: `1px solid ${t.borderL2}`,
|
|
2343
|
+
background: t.bgLayer1
|
|
2195
2344
|
};
|
|
2196
|
-
var
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2345
|
+
var rowStyle = {
|
|
2346
|
+
display: "flex",
|
|
2347
|
+
alignItems: "center",
|
|
2348
|
+
gap: "8px",
|
|
2349
|
+
padding: "16px 0",
|
|
2350
|
+
borderBottom: `1px solid ${t.borderL2}`,
|
|
2351
|
+
minWidth: "0"
|
|
2201
2352
|
};
|
|
2202
|
-
var
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2353
|
+
var rowTextStyle = {
|
|
2354
|
+
flex: "1",
|
|
2355
|
+
minWidth: "0",
|
|
2356
|
+
display: "flex",
|
|
2357
|
+
flexDirection: "column",
|
|
2358
|
+
gap: "4px",
|
|
2359
|
+
paddingRight: "48px"
|
|
2206
2360
|
};
|
|
2207
|
-
var
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
color:
|
|
2361
|
+
var rowTitleStyle = {
|
|
2362
|
+
fontSize: "14px",
|
|
2363
|
+
fontWeight: "400",
|
|
2364
|
+
lineHeight: "22px",
|
|
2365
|
+
color: t.labelPrimary
|
|
2212
2366
|
};
|
|
2213
|
-
var
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2367
|
+
var rowDescStyle = {
|
|
2368
|
+
fontSize: "12px",
|
|
2369
|
+
fontWeight: "400",
|
|
2370
|
+
lineHeight: "18px",
|
|
2371
|
+
color: t.labelTertiary
|
|
2217
2372
|
};
|
|
2218
|
-
var
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2373
|
+
var pillSelectorStyle = {
|
|
2374
|
+
display: "inline-flex",
|
|
2375
|
+
alignItems: "center",
|
|
2376
|
+
gap: "12px",
|
|
2377
|
+
height: "36px",
|
|
2378
|
+
padding: "0 14px",
|
|
2379
|
+
border: "none",
|
|
2380
|
+
borderRadius: "18px",
|
|
2381
|
+
background: "var(--dsw-alias-bg-module-platform, #F5F6F7)",
|
|
2382
|
+
font: "inherit",
|
|
2383
|
+
fontSize: "14px",
|
|
2384
|
+
lineHeight: "22px",
|
|
2385
|
+
color: t.labelPrimary,
|
|
2386
|
+
cursor: "pointer",
|
|
2387
|
+
whiteSpace: "nowrap"
|
|
2223
2388
|
};
|
|
2389
|
+
function SettingRow({ title, description, control }) {
|
|
2390
|
+
return (0, import_react.createElement)(
|
|
2391
|
+
"div",
|
|
2392
|
+
{ "data-maestro-row": "", style: rowStyle },
|
|
2393
|
+
(0, import_react.createElement)("div", { "data-maestro-row-text": "", style: rowTextStyle }, (0, import_react.createElement)("div", { style: rowTitleStyle }, title), description ? (0, import_react.createElement)("div", { style: rowDescStyle }, description) : null),
|
|
2394
|
+
(0, import_react.createElement)("div", { "data-maestro-control": "", style: { flex: "none", display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 8, minHeight: "36px" } }, control)
|
|
2395
|
+
);
|
|
2396
|
+
}
|
|
2397
|
+
function ToggleRow({ title, description, checked, onChange }) {
|
|
2398
|
+
return (0, import_react.createElement)(
|
|
2399
|
+
"label",
|
|
2400
|
+
{ "data-maestro-row": "", style: { ...rowStyle, cursor: "pointer", alignItems: "flex-start" } },
|
|
2401
|
+
(0, import_react.createElement)("input", { type: "checkbox", checked: checked === true, onChange: (e) => onChange(e.target.checked), style: { width: 16, height: 16, accentColor: t.primaryFill, marginTop: 4, flex: "none" } }),
|
|
2402
|
+
(0, import_react.createElement)("div", { "data-maestro-row-text": "", style: { ...rowTextStyle, paddingRight: "0" } }, (0, import_react.createElement)("div", { style: rowTitleStyle }, title), description ? (0, import_react.createElement)("div", { style: rowDescStyle }, description) : null)
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2224
2405
|
function QrImage({ url, size = 104 }) {
|
|
2225
2406
|
const [dataUrl, setDataUrl] = (0, import_react.useState)(null);
|
|
2226
2407
|
(0, import_react.useEffect)(() => {
|
|
@@ -2246,34 +2427,24 @@ function QrImage({ url, size = 104 }) {
|
|
|
2246
2427
|
alignItems: "center",
|
|
2247
2428
|
justifyContent: "center",
|
|
2248
2429
|
lineHeight: 0,
|
|
2249
|
-
flex: "none"
|
|
2250
|
-
alignSelf: "flex-start"
|
|
2430
|
+
flex: "none"
|
|
2251
2431
|
}
|
|
2252
2432
|
},
|
|
2253
2433
|
dataUrl === null ? (0, import_react.createElement)("div", { style: { width: size, height: size, background: "var(--dsw-alias-bg-skeleton)", borderRadius: 4 } }) : (0, import_react.createElement)("img", { src: dataUrl, alt: url, width: size, height: size, style: { display: "block" } })
|
|
2254
2434
|
);
|
|
2255
2435
|
}
|
|
2256
|
-
function
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel login"),
|
|
2265
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel create dsh-maestro-webhook"),
|
|
2266
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel route dns dsh-maestro-webhook <your-hostname>"),
|
|
2267
|
-
(0, import_react.createElement)("li", null, "Paste the printed Tunnel ID, the credentials file path (~/.cloudflared/<id>.json), and the hostname below.")
|
|
2268
|
-
)
|
|
2269
|
-
);
|
|
2270
|
-
}
|
|
2271
|
-
function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onChange, label }) {
|
|
2436
|
+
function ReviewModelSelector({
|
|
2437
|
+
value,
|
|
2438
|
+
catalog,
|
|
2439
|
+
fallbackValue,
|
|
2440
|
+
fallbackLabel,
|
|
2441
|
+
onChange,
|
|
2442
|
+
label
|
|
2443
|
+
}) {
|
|
2272
2444
|
const groups = catalog?.groups ?? [];
|
|
2273
2445
|
const providers = groups.map((g) => g.provider);
|
|
2274
2446
|
const selectedProvider = value?.provider ?? "";
|
|
2275
2447
|
const providerGroup = groups.find((g) => g.provider === selectedProvider);
|
|
2276
|
-
const models = providerGroup?.models ?? [];
|
|
2277
2448
|
const selectedEffort = value?.reasoningEffort ?? "";
|
|
2278
2449
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
2279
2450
|
const [pane, setPane] = (0, import_react.useState)("root");
|
|
@@ -2321,7 +2492,7 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2321
2492
|
if (filtered.length > 0) return filtered;
|
|
2322
2493
|
return ["low", "medium", "high"];
|
|
2323
2494
|
})();
|
|
2324
|
-
const warning = selectedEffort !== "" && !supportsReasoning && selectedModelInfo !== null ? `\u26A0\uFE0F This model does not support reasoning effort "${selectedEffort}" \u2014 reviews will fail
|
|
2495
|
+
const warning = selectedEffort !== "" && !supportsReasoning && selectedModelInfo !== null ? `\u26A0\uFE0F This model does not support reasoning effort "${selectedEffort}" \u2014 reviews will fail.` : null;
|
|
2325
2496
|
const update = (field, newVal) => {
|
|
2326
2497
|
if (newVal === "" && field === "provider") {
|
|
2327
2498
|
onChange(null);
|
|
@@ -2335,51 +2506,30 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2335
2506
|
const first = g?.models[0];
|
|
2336
2507
|
next.provider = newVal;
|
|
2337
2508
|
next.model = first !== void 0 ? getModelId(first) : "";
|
|
2338
|
-
} else if (field === "model")
|
|
2339
|
-
|
|
2340
|
-
} else if (field === "reasoningEffort") {
|
|
2509
|
+
} else if (field === "model") next.model = newVal;
|
|
2510
|
+
else if (field === "reasoningEffort") {
|
|
2341
2511
|
if (newVal === "") delete next.reasoningEffort;
|
|
2342
2512
|
else next.reasoningEffort = newVal;
|
|
2343
2513
|
}
|
|
2344
|
-
if (!next.provider || !next.model)
|
|
2345
|
-
|
|
2346
|
-
} else {
|
|
2347
|
-
onChange(next);
|
|
2348
|
-
}
|
|
2514
|
+
if (!next.provider || !next.model) onChange(null);
|
|
2515
|
+
else onChange(next);
|
|
2349
2516
|
};
|
|
2350
2517
|
const effectiveFallback = fallbackValue !== void 0 ? fallbackValue : catalog?.current ?? null;
|
|
2351
|
-
const
|
|
2352
|
-
const triggerLabel = value ? `${value.provider} / ${value.model}${value.reasoningEffort ? ` \xB7 ${value.reasoningEffort}` : ""}` : effectiveFallback ? `${effectiveFallbackLabel} \xB7 ${effectiveFallback.provider}/${effectiveFallback.model}${effectiveFallback.reasoningEffort ? ` \xB7 ${effectiveFallback.reasoningEffort}` : ""}` : effectiveFallbackLabel;
|
|
2353
|
-
const triggerStyle = {
|
|
2354
|
-
height: 32,
|
|
2355
|
-
padding: "0 12px 0 14px",
|
|
2356
|
-
borderRadius: 20,
|
|
2357
|
-
border: "1px solid var(--dsw-alias-border-l2)",
|
|
2358
|
-
background: "var(--dsw-alias-bg-layer-2)",
|
|
2359
|
-
color: "var(--dsw-alias-label-primary)",
|
|
2360
|
-
font: "inherit",
|
|
2361
|
-
fontSize: 13,
|
|
2362
|
-
display: "inline-flex",
|
|
2363
|
-
alignItems: "center",
|
|
2364
|
-
gap: 8,
|
|
2365
|
-
cursor: "pointer",
|
|
2366
|
-
maxWidth: 320,
|
|
2367
|
-
whiteSpace: "nowrap"
|
|
2368
|
-
};
|
|
2518
|
+
const triggerLabel = value ? `${value.provider} / ${value.model}${value.reasoningEffort ? ` \xB7 ${value.reasoningEffort}` : ""}` : effectiveFallback ? `${fallbackLabel} \xB7 ${effectiveFallback.provider}/${effectiveFallback.model}${effectiveFallback.reasoningEffort ? ` \xB7 ${effectiveFallback.reasoningEffort}` : ""}` : fallbackLabel;
|
|
2369
2519
|
const menuStyle = {
|
|
2370
2520
|
position: "absolute",
|
|
2371
2521
|
top: "calc(100% + 8px)",
|
|
2372
|
-
left: 0,
|
|
2373
|
-
minWidth:
|
|
2374
|
-
maxWidth:
|
|
2375
|
-
background:
|
|
2376
|
-
border:
|
|
2377
|
-
borderRadius:
|
|
2378
|
-
boxShadow:
|
|
2379
|
-
zIndex: 20,
|
|
2380
|
-
padding:
|
|
2522
|
+
left: "0",
|
|
2523
|
+
minWidth: "300px",
|
|
2524
|
+
maxWidth: "360px",
|
|
2525
|
+
background: t.bgLayer2,
|
|
2526
|
+
border: `1px solid ${t.borderL2}`,
|
|
2527
|
+
borderRadius: "12px",
|
|
2528
|
+
boxShadow: t.shadowLv3,
|
|
2529
|
+
zIndex: "20",
|
|
2530
|
+
padding: "6px"
|
|
2381
2531
|
};
|
|
2382
|
-
const
|
|
2532
|
+
const rowStyle2 = {
|
|
2383
2533
|
width: "100%",
|
|
2384
2534
|
display: "flex",
|
|
2385
2535
|
alignItems: "center",
|
|
@@ -2389,66 +2539,87 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2389
2539
|
borderRadius: 8,
|
|
2390
2540
|
border: "none",
|
|
2391
2541
|
background: "transparent",
|
|
2392
|
-
color:
|
|
2393
|
-
|
|
2542
|
+
color: t.labelPrimary,
|
|
2543
|
+
fontFamily: "inherit",
|
|
2394
2544
|
fontSize: 13,
|
|
2395
2545
|
cursor: "pointer",
|
|
2396
2546
|
textAlign: "left"
|
|
2397
2547
|
};
|
|
2398
2548
|
const check = (active) => active ? (0, import_react.createElement)("svg", { width: 16, height: 16, viewBox: "0 0 16 16", style: { flex: "none" } }, (0, import_react.createElement)("path", { d: "M3.5 8.2l2.8 2.8L12.5 4.8", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" })) : (0, import_react.createElement)("span", { style: { width: 16, flex: "none" } });
|
|
2399
|
-
const chevronDown = (0, import_react.createElement)("svg", { width: 14, height: 14, viewBox: "0 0 14 14", style: { flex: "none", opacity: 0.7 } }, (0, import_react.createElement)("path", { d: "M3.5 5L7 8.5L10.5 5", fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
2400
2549
|
const chevronRight = (0, import_react.createElement)("svg", { width: 14, height: 14, viewBox: "0 0 14 14", style: { flex: "none", opacity: 0.6 } }, (0, import_react.createElement)("path", { d: "M5 3.5L8.5 7L5 10.5", fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
2401
2550
|
const effortLabel = selectedEffort === "" ? "Default effort" : selectedEffort;
|
|
2402
2551
|
const modelLabel = selectedProvider === "" ? "Select model" : value?.model ?? "Select model";
|
|
2403
2552
|
return (0, import_react.createElement)(
|
|
2404
2553
|
"div",
|
|
2405
|
-
{ ref: rootRef, style: { position: "relative", display: "inline-block", maxWidth: "100%" } },
|
|
2406
|
-
label
|
|
2554
|
+
{ ref: rootRef, "data-maestro-trigger-wrap": "", style: { position: "relative", display: "inline-block", maxWidth: "100%" } },
|
|
2555
|
+
label ? (0, import_react.createElement)("span", { style: fieldLabelStyle }, label) : null,
|
|
2407
2556
|
(0, import_react.createElement)(
|
|
2408
2557
|
"button",
|
|
2409
|
-
{
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2558
|
+
{
|
|
2559
|
+
type: "button",
|
|
2560
|
+
style: {
|
|
2561
|
+
height: 36,
|
|
2562
|
+
padding: "0 14px 0 16px",
|
|
2563
|
+
borderRadius: 18,
|
|
2564
|
+
border: "none",
|
|
2565
|
+
background: "var(--dsw-alias-bg-module-platform, #F5F6F7)",
|
|
2566
|
+
color: t.labelPrimary,
|
|
2567
|
+
fontFamily: "inherit",
|
|
2568
|
+
fontSize: 13,
|
|
2569
|
+
display: "inline-flex",
|
|
2570
|
+
alignItems: "center",
|
|
2571
|
+
gap: 8,
|
|
2572
|
+
cursor: "pointer",
|
|
2573
|
+
maxWidth: 320,
|
|
2574
|
+
whiteSpace: "nowrap"
|
|
2575
|
+
},
|
|
2576
|
+
onClick: () => {
|
|
2577
|
+
setOpen((v) => !v);
|
|
2578
|
+
setPane("root");
|
|
2579
|
+
},
|
|
2580
|
+
"aria-expanded": open,
|
|
2581
|
+
"aria-haspopup": "menu",
|
|
2582
|
+
title: triggerLabel
|
|
2583
|
+
},
|
|
2413
2584
|
(0, import_react.createElement)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, triggerLabel),
|
|
2414
|
-
|
|
2585
|
+
(0, import_react.createElement)("svg", { width: 14, height: 14, viewBox: "0 0 14 14", style: { flex: "none", opacity: 0.7 } }, (0, import_react.createElement)("path", { d: "M3.5 5L7 8.5L10.5 5", fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round" }))
|
|
2415
2586
|
),
|
|
2416
|
-
open
|
|
2587
|
+
open ? (0, import_react.createElement)(
|
|
2417
2588
|
"div",
|
|
2418
|
-
{ style: menuStyle, role: "menu" },
|
|
2419
|
-
pane === "root"
|
|
2589
|
+
{ "data-maestro-menu": "", style: menuStyle, role: "menu" },
|
|
2590
|
+
pane === "root" ? (0, import_react.createElement)(
|
|
2420
2591
|
"div",
|
|
2421
2592
|
null,
|
|
2422
2593
|
(0, import_react.createElement)(
|
|
2423
2594
|
"button",
|
|
2424
|
-
{ type: "button", style: { ...
|
|
2595
|
+
{ type: "button", style: { ...rowStyle2, background: !value ? t.bgLayer1 : "transparent" }, onClick: () => {
|
|
2425
2596
|
onChange(null);
|
|
2426
2597
|
setOpen(false);
|
|
2427
2598
|
} },
|
|
2428
|
-
(0, import_react.createElement)("span", null,
|
|
2599
|
+
(0, import_react.createElement)("span", null, fallbackLabel),
|
|
2429
2600
|
check(!value)
|
|
2430
2601
|
),
|
|
2431
|
-
(0, import_react.createElement)("div", { style: { height: 1, background:
|
|
2602
|
+
(0, import_react.createElement)("div", { style: { height: 1, background: t.borderL2, margin: "6px 2px" } }),
|
|
2432
2603
|
(0, import_react.createElement)(
|
|
2433
2604
|
"button",
|
|
2434
|
-
{ type: "button", style:
|
|
2605
|
+
{ type: "button", style: rowStyle2, onClick: () => setPane("model") },
|
|
2435
2606
|
(0, import_react.createElement)("span", null, "Model"),
|
|
2436
|
-
(0, import_react.createElement)("span", { style: { display: "flex", alignItems: "center", gap: 8, color:
|
|
2607
|
+
(0, import_react.createElement)("span", { style: { display: "flex", alignItems: "center", gap: 8, color: t.labelSecondary, maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, (0, import_react.createElement)("span", { style: { overflow: "hidden", textOverflow: "ellipsis" } }, modelLabel), chevronRight)
|
|
2437
2608
|
),
|
|
2438
2609
|
(0, import_react.createElement)(
|
|
2439
2610
|
"button",
|
|
2440
|
-
{ type: "button", style:
|
|
2611
|
+
{ type: "button", style: rowStyle2, onClick: () => setPane("effort") },
|
|
2441
2612
|
(0, import_react.createElement)("span", null, "Effort"),
|
|
2442
|
-
(0, import_react.createElement)("span", { style: { display: "flex", alignItems: "center", gap: 8, color:
|
|
2613
|
+
(0, import_react.createElement)("span", { style: { display: "flex", alignItems: "center", gap: 8, color: t.labelSecondary } }, effortLabel, chevronRight)
|
|
2443
2614
|
),
|
|
2444
|
-
value
|
|
2445
|
-
!value && effectiveFallback
|
|
2446
|
-
warning
|
|
2447
|
-
),
|
|
2448
|
-
pane === "model"
|
|
2615
|
+
value ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px" } }, `Selected: ${value.provider} / ${value.model}${value.reasoningEffort ? ` (${value.reasoningEffort})` : ""}`) : null,
|
|
2616
|
+
!value && effectiveFallback ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px" } }, `${fallbackLabel === "Use Global" ? "Using Global" : "Using DSH default"}: ${effectiveFallback.provider} / ${effectiveFallback.model}${effectiveFallback.reasoningEffort ? ` (${effectiveFallback.reasoningEffort})` : ""}`) : null,
|
|
2617
|
+
warning ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "4px 4px 2px", color: t.stateError } }, warning) : null
|
|
2618
|
+
) : null,
|
|
2619
|
+
pane === "model" ? (0, import_react.createElement)(
|
|
2449
2620
|
"div",
|
|
2450
2621
|
null,
|
|
2451
|
-
(0, import_react.createElement)("button", { type: "button", style: { ...
|
|
2622
|
+
(0, import_react.createElement)("button", { type: "button", style: { ...rowStyle2, color: t.labelSecondary }, onClick: () => setPane("root") }, (0, import_react.createElement)("span", null, "\u2190 Back"), (0, import_react.createElement)("span", { style: { fontSize: 12 } }, "Model")),
|
|
2452
2623
|
(0, import_react.createElement)(
|
|
2453
2624
|
"div",
|
|
2454
2625
|
{ style: { maxHeight: 260, overflowY: "auto", marginTop: 4 } },
|
|
@@ -2458,33 +2629,43 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2458
2629
|
return (0, import_react.createElement)(
|
|
2459
2630
|
"div",
|
|
2460
2631
|
{ key: p, style: { marginBottom: 8 } },
|
|
2461
|
-
(0, import_react.createElement)("div", { style: { fontSize: 11, fontWeight: 600, color:
|
|
2632
|
+
(0, import_react.createElement)("div", { style: { fontSize: 11, fontWeight: 600, color: t.labelSecondary, padding: "6px 10px 2px", textTransform: "uppercase", letterSpacing: 0.4, display: "flex", alignItems: "center", gap: 6 } }, (0, import_react.createElement)("span", { style: { width: 6, height: 6, borderRadius: 3, background: t.borderL2, flex: "none" } }), g?.name ?? p),
|
|
2462
2633
|
ms.length === 0 ? (0, import_react.createElement)("p", { style: { ...captionStyle, padding: "2px 10px 2px 28px" } }, "No models") : (0, import_react.createElement)(
|
|
2463
2634
|
"div",
|
|
2464
|
-
{ style: { marginLeft: 12, borderLeft:
|
|
2635
|
+
{ style: { marginLeft: 12, borderLeft: `1px solid ${t.borderL2}`, paddingLeft: 6, display: "flex", flexDirection: "column", gap: 2 } },
|
|
2465
2636
|
ms.map((m) => {
|
|
2466
2637
|
const mid = getModelId(m);
|
|
2467
2638
|
const mname = getModelName(m);
|
|
2468
2639
|
const active = value?.provider === p && value?.model === mid;
|
|
2469
|
-
return (0, import_react.createElement)(
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2640
|
+
return (0, import_react.createElement)(
|
|
2641
|
+
"button",
|
|
2642
|
+
{
|
|
2643
|
+
key: mid,
|
|
2644
|
+
type: "button",
|
|
2645
|
+
style: { ...rowStyle2, paddingLeft: 10, background: active ? t.bgLayer1 : "transparent" },
|
|
2646
|
+
onClick: () => {
|
|
2647
|
+
update("model", mid);
|
|
2648
|
+
if (value?.provider !== p) update("provider", p);
|
|
2649
|
+
else {
|
|
2650
|
+
const next = { provider: p, model: mid, ...selectedEffort ? { reasoningEffort: selectedEffort } : {} };
|
|
2651
|
+
onChange(next);
|
|
2652
|
+
setPane("root");
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
},
|
|
2656
|
+
(0, import_react.createElement)("span", { style: { overflow: "hidden", textOverflow: "ellipsis" } }, mname),
|
|
2657
|
+
check(active)
|
|
2658
|
+
);
|
|
2478
2659
|
})
|
|
2479
2660
|
)
|
|
2480
2661
|
);
|
|
2481
2662
|
})
|
|
2482
2663
|
)
|
|
2483
|
-
),
|
|
2484
|
-
pane === "effort"
|
|
2664
|
+
) : null,
|
|
2665
|
+
pane === "effort" ? (0, import_react.createElement)(
|
|
2485
2666
|
"div",
|
|
2486
2667
|
null,
|
|
2487
|
-
(0, import_react.createElement)("button", { type: "button", style: { ...
|
|
2668
|
+
(0, import_react.createElement)("button", { type: "button", style: { ...rowStyle2, color: t.labelSecondary }, onClick: () => setPane("root") }, (0, import_react.createElement)("span", null, "\u2190 Back"), (0, import_react.createElement)("span", { style: { fontSize: 12 } }, "Effort")),
|
|
2488
2669
|
selectedModelInfo === null ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px" } }, "Select a model first to configure effort.") : !supportsReasoning ? (0, import_react.createElement)(
|
|
2489
2670
|
"div",
|
|
2490
2671
|
null,
|
|
@@ -2492,133 +2673,228 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2492
2673
|
(0, import_react.createElement)(
|
|
2493
2674
|
"div",
|
|
2494
2675
|
{ style: { marginTop: 4 } },
|
|
2495
|
-
[{ id: "", label: "Default effort" }].map(
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2676
|
+
[{ id: "", label: "Default effort" }].map(
|
|
2677
|
+
(e) => (0, import_react.createElement)(
|
|
2678
|
+
"button",
|
|
2679
|
+
{ key: e.id || "default", type: "button", style: { ...rowStyle2, background: selectedEffort === e.id ? t.bgLayer1 : "transparent" }, onClick: () => {
|
|
2680
|
+
update("reasoningEffort", e.id);
|
|
2681
|
+
setPane("root");
|
|
2682
|
+
} },
|
|
2683
|
+
(0, import_react.createElement)("span", null, e.label),
|
|
2684
|
+
check(selectedEffort === e.id)
|
|
2685
|
+
)
|
|
2686
|
+
)
|
|
2499
2687
|
),
|
|
2500
|
-
warning
|
|
2688
|
+
warning ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px", color: t.stateError } }, warning) : null
|
|
2501
2689
|
) : (0, import_react.createElement)(
|
|
2502
2690
|
"div",
|
|
2503
2691
|
null,
|
|
2504
2692
|
(0, import_react.createElement)(
|
|
2505
2693
|
"div",
|
|
2506
2694
|
{ style: { marginTop: 4 } },
|
|
2507
|
-
[{ id: "", label: "Default effort" }, ...availableEfforts.map((id) => ({ id, label: id }))].map(
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2695
|
+
[{ id: "", label: "Default effort" }, ...availableEfforts.map((id) => ({ id, label: id }))].map(
|
|
2696
|
+
(e) => (0, import_react.createElement)(
|
|
2697
|
+
"button",
|
|
2698
|
+
{ key: e.id || "default", type: "button", style: { ...rowStyle2, background: selectedEffort === e.id ? t.bgLayer1 : "transparent" }, onClick: () => {
|
|
2699
|
+
update("reasoningEffort", e.id);
|
|
2700
|
+
setPane("root");
|
|
2701
|
+
} },
|
|
2702
|
+
(0, import_react.createElement)("span", null, e.label),
|
|
2703
|
+
check(selectedEffort === e.id)
|
|
2704
|
+
)
|
|
2705
|
+
)
|
|
2511
2706
|
),
|
|
2512
|
-
warning
|
|
2707
|
+
warning ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px", color: t.stateError } }, warning) : null
|
|
2513
2708
|
)
|
|
2514
|
-
)
|
|
2515
|
-
)
|
|
2709
|
+
) : null
|
|
2710
|
+
) : null
|
|
2516
2711
|
);
|
|
2517
2712
|
}
|
|
2518
2713
|
function ProjectMappingsEditor({ mappings, onChange, catalog, globalReviewModel }) {
|
|
2519
|
-
const rows = mappings
|
|
2714
|
+
const rows = mappings;
|
|
2520
2715
|
const updateRow = (index, field, value) => {
|
|
2521
2716
|
const next = rows.map((row, i) => i === index ? { ...row, [field]: value } : row);
|
|
2522
|
-
onChange(next.filter((r) => r.projectPath !== "" || r.localRepoPath !== ""));
|
|
2717
|
+
onChange(next.filter((r) => (r.projectPath ?? "") !== "" || (r.localRepoPath ?? "") !== ""));
|
|
2523
2718
|
};
|
|
2524
2719
|
const removeRow = (index) => onChange(rows.filter((_, i) => i !== index));
|
|
2525
2720
|
const addRow = () => onChange([...rows, { projectPath: "", localRepoPath: "", reviewProfile: "magento2" }]);
|
|
2526
2721
|
return (0, import_react.createElement)(
|
|
2527
2722
|
"div",
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2723
|
+
{ "data-maestro-projects": "", style: { display: "flex", flexDirection: "column", gap: 12, paddingTop: 8 } },
|
|
2724
|
+
// Header — count + primary Add
|
|
2725
|
+
(0, import_react.createElement)(
|
|
2531
2726
|
"div",
|
|
2532
|
-
{
|
|
2533
|
-
(0, import_react.createElement)("input", { placeholder: "group/project", style: { ...inputStyle, flex: "1 1 120px" }, value: row.projectPath, onChange: (e) => updateRow(i, "projectPath", e.target.value) }),
|
|
2534
|
-
(0, import_react.createElement)("input", { placeholder: "/path/to/local/clone", style: { ...inputStyle, flex: "1 1 140px" }, value: row.localRepoPath, onChange: (e) => updateRow(i, "localRepoPath", e.target.value) }),
|
|
2535
|
-
(0, import_react.createElement)(
|
|
2536
|
-
"select",
|
|
2537
|
-
{ style: { ...inputStyle, flex: "0 0 130px" }, value: row.reviewProfile ?? "magento2", onChange: (e) => updateRow(i, "reviewProfile", e.target.value) },
|
|
2538
|
-
(0, import_react.createElement)("option", { value: "magento2" }, "Magento 2"),
|
|
2539
|
-
(0, import_react.createElement)("option", { value: "generic" }, "Generic")
|
|
2540
|
-
),
|
|
2727
|
+
{ style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12, padding: "4px 0 4px" } },
|
|
2541
2728
|
(0, import_react.createElement)(
|
|
2542
2729
|
"div",
|
|
2543
|
-
{ style: { flex:
|
|
2544
|
-
(0, import_react.createElement)(
|
|
2545
|
-
|
|
2546
|
-
catalog,
|
|
2547
|
-
fallbackValue: globalReviewModel ?? catalog?.current ?? null,
|
|
2548
|
-
fallbackLabel: globalReviewModel ? "Use Global" : "Use DSH default",
|
|
2549
|
-
onChange: (v) => updateRow(i, "reviewModel", v),
|
|
2550
|
-
label: null
|
|
2551
|
-
})
|
|
2730
|
+
{ style: { flex: 1, minWidth: 0 } },
|
|
2731
|
+
(0, import_react.createElement)("div", { style: { fontSize: 14, fontWeight: 600, color: t.labelPrimary, lineHeight: "20px" } }, `Projects \u2014 ${rows.length} tracked`),
|
|
2732
|
+
(0, import_react.createElement)("div", { style: { fontSize: 12, color: t.labelSecondary, lineHeight: "16px", marginTop: 2 } }, "GitLab path \u2192 local checkout \u2192 profile \u2192 model override")
|
|
2552
2733
|
),
|
|
2553
|
-
(0, import_react.createElement)(
|
|
2554
|
-
)
|
|
2555
|
-
(0, import_react.createElement)(
|
|
2556
|
-
);
|
|
2557
|
-
}
|
|
2558
|
-
function SecretInput({ label, placeholder, hasSaved, onSave }) {
|
|
2559
|
-
const [draft, setDraft] = (0, import_react.useState)("");
|
|
2560
|
-
const clear = () => {
|
|
2561
|
-
setDraft("");
|
|
2562
|
-
onSave("");
|
|
2563
|
-
};
|
|
2564
|
-
return (0, import_react.createElement)(
|
|
2565
|
-
"div",
|
|
2566
|
-
null,
|
|
2567
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, label),
|
|
2568
|
-
(0, import_react.createElement)(
|
|
2734
|
+
(0, import_react.createElement)(Button, { variant: "primary", size: "md", onClick: addRow }, "+ Add project")
|
|
2735
|
+
),
|
|
2736
|
+
rows.length === 0 ? (0, import_react.createElement)(
|
|
2569
2737
|
"div",
|
|
2570
|
-
{
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2738
|
+
{
|
|
2739
|
+
"data-maestro-project-empty": "",
|
|
2740
|
+
style: {
|
|
2741
|
+
display: "flex",
|
|
2742
|
+
flexDirection: "column",
|
|
2743
|
+
alignItems: "center",
|
|
2744
|
+
gap: 10,
|
|
2745
|
+
padding: "20px 16px",
|
|
2746
|
+
borderRadius: 12,
|
|
2747
|
+
border: `1px dashed ${t.borderL2}`,
|
|
2748
|
+
background: "transparent",
|
|
2749
|
+
textAlign: "center"
|
|
2580
2750
|
}
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2751
|
+
},
|
|
2752
|
+
(0, import_react.createElement)("div", { style: { fontSize: 13, color: t.labelSecondary, lineHeight: "18px" } }, "No projects yet \u2014 add your first mapping"),
|
|
2753
|
+
(0, import_react.createElement)(Button, { variant: "outline", size: "md", onClick: addRow }, "+ Add project")
|
|
2754
|
+
) : (0, import_react.createElement)(
|
|
2755
|
+
"div",
|
|
2756
|
+
{ style: { display: "flex", flexDirection: "column", gap: 12 } },
|
|
2757
|
+
...rows.map(
|
|
2758
|
+
(row, i) => (0, import_react.createElement)(
|
|
2759
|
+
"div",
|
|
2760
|
+
{
|
|
2761
|
+
key: i,
|
|
2762
|
+
"data-maestro-project-card": "",
|
|
2763
|
+
style: {
|
|
2764
|
+
display: "flex",
|
|
2765
|
+
flexDirection: "column",
|
|
2766
|
+
gap: 12,
|
|
2767
|
+
padding: 12,
|
|
2768
|
+
borderRadius: 12,
|
|
2769
|
+
border: `1px solid ${t.borderL2}`,
|
|
2770
|
+
background: t.bgLayer1,
|
|
2771
|
+
boxSizing: "border-box"
|
|
2772
|
+
}
|
|
2773
|
+
},
|
|
2774
|
+
// Card header: index + path + remove
|
|
2775
|
+
(0, import_react.createElement)(
|
|
2776
|
+
"div",
|
|
2777
|
+
{ style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 } },
|
|
2778
|
+
(0, import_react.createElement)(
|
|
2779
|
+
"div",
|
|
2780
|
+
{ style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0, flex: 1 } },
|
|
2781
|
+
(0, import_react.createElement)(
|
|
2782
|
+
"span",
|
|
2783
|
+
{
|
|
2784
|
+
style: {
|
|
2785
|
+
flex: "none",
|
|
2786
|
+
width: 24,
|
|
2787
|
+
height: 24,
|
|
2788
|
+
borderRadius: 12,
|
|
2789
|
+
background: "var(--dsw-alias-bg-module-platform, #F5F6F7)",
|
|
2790
|
+
display: "inline-flex",
|
|
2791
|
+
alignItems: "center",
|
|
2792
|
+
justifyContent: "center",
|
|
2793
|
+
fontSize: 11,
|
|
2794
|
+
fontWeight: 600,
|
|
2795
|
+
color: t.labelSecondary
|
|
2796
|
+
}
|
|
2797
|
+
},
|
|
2798
|
+
String(i + 1)
|
|
2799
|
+
),
|
|
2800
|
+
(0, import_react.createElement)(
|
|
2801
|
+
"span",
|
|
2802
|
+
{
|
|
2803
|
+
style: {
|
|
2804
|
+
fontSize: 12,
|
|
2805
|
+
fontFamily: "ui-monospace, monospace",
|
|
2806
|
+
color: row.projectPath ? t.labelPrimary : t.labelTertiary,
|
|
2807
|
+
overflow: "hidden",
|
|
2808
|
+
textOverflow: "ellipsis",
|
|
2809
|
+
whiteSpace: "nowrap",
|
|
2810
|
+
minWidth: 0
|
|
2811
|
+
}
|
|
2812
|
+
},
|
|
2813
|
+
row.projectPath || "Untitled project"
|
|
2814
|
+
)
|
|
2815
|
+
),
|
|
2816
|
+
(0, import_react.createElement)(
|
|
2817
|
+
Button,
|
|
2818
|
+
{ variant: "outline", size: "sm", onClick: () => removeRow(i), "aria-label": `Remove project ${i + 1}`, title: "Remove mapping" },
|
|
2819
|
+
"\u2715"
|
|
2820
|
+
)
|
|
2821
|
+
),
|
|
2822
|
+
// Grid 2-col for paths
|
|
2823
|
+
(0, import_react.createElement)(
|
|
2824
|
+
"div",
|
|
2825
|
+
{ "data-maestro-project-grid": "", style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 } },
|
|
2826
|
+
(0, import_react.createElement)(
|
|
2827
|
+
"label",
|
|
2828
|
+
{ style: fieldLabelStyle, "data-maestro-field": "" },
|
|
2829
|
+
"GitLab path",
|
|
2830
|
+
(0, import_react.createElement)(FieldInput, {
|
|
2831
|
+
placeholder: "group/project",
|
|
2832
|
+
value: row.projectPath,
|
|
2833
|
+
onChange: (e) => updateRow(i, "projectPath", e.target.value),
|
|
2834
|
+
"aria-label": `GitLab path ${i + 1}`,
|
|
2835
|
+
style: { width: "100%" }
|
|
2836
|
+
})
|
|
2837
|
+
),
|
|
2838
|
+
(0, import_react.createElement)(
|
|
2839
|
+
"label",
|
|
2840
|
+
{ style: fieldLabelStyle, "data-maestro-field": "" },
|
|
2841
|
+
"Local checkout",
|
|
2842
|
+
(0, import_react.createElement)(FieldInput, {
|
|
2843
|
+
placeholder: "/path/to/local/clone",
|
|
2844
|
+
value: row.localRepoPath,
|
|
2845
|
+
onChange: (e) => updateRow(i, "localRepoPath", e.target.value),
|
|
2846
|
+
"aria-label": `Local checkout ${i + 1}`,
|
|
2847
|
+
style: { width: "100%" }
|
|
2848
|
+
})
|
|
2849
|
+
)
|
|
2850
|
+
),
|
|
2851
|
+
// Row for profile + model — unified label+control, gap 12, pill h36
|
|
2852
|
+
(0, import_react.createElement)(
|
|
2853
|
+
"div",
|
|
2854
|
+
{ "data-maestro-project-profile-row": "", style: { display: "flex", gap: 12, flexWrap: "wrap", alignItems: "flex-start" } },
|
|
2855
|
+
(0, import_react.createElement)(
|
|
2856
|
+
"label",
|
|
2857
|
+
{ style: { ...fieldLabelStyle, flex: "1 1 160px", minWidth: 0 } },
|
|
2858
|
+
"Review profile",
|
|
2859
|
+
(0, import_react.createElement)(
|
|
2860
|
+
"select",
|
|
2861
|
+
{
|
|
2862
|
+
value: row.reviewProfile ?? "magento2",
|
|
2863
|
+
onChange: (e) => updateRow(i, "reviewProfile", e.target.value),
|
|
2864
|
+
"aria-label": `Review profile ${i + 1}`,
|
|
2865
|
+
style: {
|
|
2866
|
+
height: 36,
|
|
2867
|
+
width: "100%",
|
|
2868
|
+
padding: "0 14px",
|
|
2869
|
+
border: "none",
|
|
2870
|
+
borderRadius: 18,
|
|
2871
|
+
background: "var(--dsw-alias-bg-module-platform, #F5F6F7)",
|
|
2872
|
+
color: t.labelPrimary,
|
|
2873
|
+
font: "inherit",
|
|
2874
|
+
fontSize: 13
|
|
2875
|
+
}
|
|
2876
|
+
},
|
|
2877
|
+
(0, import_react.createElement)("option", { value: "magento2" }, "Magento 2"),
|
|
2878
|
+
(0, import_react.createElement)("option", { value: "generic" }, "Generic")
|
|
2879
|
+
)
|
|
2880
|
+
),
|
|
2881
|
+
(0, import_react.createElement)(
|
|
2882
|
+
"label",
|
|
2883
|
+
{ style: { ...fieldLabelStyle, flex: "1 1 200px", minWidth: 0 } },
|
|
2884
|
+
"Model override",
|
|
2885
|
+
(0, import_react.createElement)(ReviewModelSelector, {
|
|
2886
|
+
value: row.reviewModel ?? null,
|
|
2887
|
+
catalog,
|
|
2888
|
+
fallbackValue: globalReviewModel ?? catalog?.current ?? null,
|
|
2889
|
+
fallbackLabel: globalReviewModel ? "Use Global" : "Use DSH default",
|
|
2890
|
+
onChange: (v) => updateRow(i, "reviewModel", v),
|
|
2891
|
+
label: null
|
|
2892
|
+
})
|
|
2893
|
+
)
|
|
2894
|
+
)
|
|
2895
|
+
)
|
|
2620
2896
|
)
|
|
2621
|
-
)
|
|
2897
|
+
)
|
|
2622
2898
|
);
|
|
2623
2899
|
}
|
|
2624
2900
|
function LanAccess({ proxyStatus, lanPin }) {
|
|
@@ -2626,40 +2902,26 @@ function LanAccess({ proxyStatus, lanPin }) {
|
|
|
2626
2902
|
const [selected, setSelected] = (0, import_react.useState)(0);
|
|
2627
2903
|
const index = Math.min(selected, Math.max(urls.length - 1, 0));
|
|
2628
2904
|
if (!proxyStatus?.running) {
|
|
2629
|
-
return (0, import_react.createElement)("p", { style:
|
|
2905
|
+
return (0, import_react.createElement)("p", { style: { color: t.stateError, fontSize: 12, margin: "8px 0 0" } }, proxyStatus?.errorMessage ?? "Proxy not running");
|
|
2630
2906
|
}
|
|
2631
2907
|
return (0, import_react.createElement)(
|
|
2632
2908
|
"div",
|
|
2633
2909
|
null,
|
|
2634
|
-
(0, import_react.createElement)("p", { style: captionStyle }, lanPin?.enabled === true ? "Open this
|
|
2635
|
-
urls.length > 0
|
|
2910
|
+
(0, import_react.createElement)("p", { style: captionStyle }, lanPin?.enabled === true ? "Open this DSH UI from any device on your network \u2014 visitors enter the LAN PIN below." : "Open this DSH UI from any device on your network \u2014 no PIN needed."),
|
|
2911
|
+
urls.length > 0 ? (0, import_react.createElement)(
|
|
2636
2912
|
"div",
|
|
2637
2913
|
{ style: { display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 } },
|
|
2638
|
-
urls.map(
|
|
2639
|
-
key: url,
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
height: 26,
|
|
2644
|
-
padding: "0 10px",
|
|
2645
|
-
fontSize: 12,
|
|
2646
|
-
borderRadius: 13,
|
|
2647
|
-
...i === index ? { background: "var(--dsw-alias-button-primary-fill)", borderColor: "transparent", color: "var(--dsw-alias-label-primary-foreground)" } : {}
|
|
2648
|
-
}
|
|
2649
|
-
}, url.replace(/^http:\/\//, "")))
|
|
2650
|
-
),
|
|
2651
|
-
urls.length > 0 && (0, import_react.createElement)(
|
|
2914
|
+
...urls.map(
|
|
2915
|
+
(url, i) => (0, import_react.createElement)(Button, { key: url, variant: i === index ? "primary" : "outline", size: "sm", onClick: () => setSelected(i) }, url.replace(/^http:\/\//, ""))
|
|
2916
|
+
)
|
|
2917
|
+
) : null,
|
|
2918
|
+
urls.length > 0 ? (0, import_react.createElement)(
|
|
2652
2919
|
"div",
|
|
2653
|
-
{ style: { display: "flex", gap: 14, alignItems: "center" } },
|
|
2920
|
+
{ "data-maestro-qr-row": "", style: { display: "flex", gap: 14, alignItems: "center", flexWrap: "wrap" } },
|
|
2654
2921
|
(0, import_react.createElement)(QrImage, { url: urls[index], size: 116 }),
|
|
2655
|
-
(0, import_react.createElement)(
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
(0, import_react.createElement)("div", { style: codeStyle }, urls[index]),
|
|
2659
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Scan with a phone connected to the same network.")
|
|
2660
|
-
)
|
|
2661
|
-
),
|
|
2662
|
-
lanPin !== null && (0, import_react.createElement)(LanPinRow, { lanPin })
|
|
2922
|
+
(0, import_react.createElement)("div", null, (0, import_react.createElement)("div", { style: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12, color: t.labelPrimary, wordBreak: "break-all" } }, urls[index]), (0, import_react.createElement)("p", { style: captionStyle }, "Scan with a phone on the same network."))
|
|
2923
|
+
) : null,
|
|
2924
|
+
lanPin !== null ? (0, import_react.createElement)(LanPinRow, { lanPin }) : null
|
|
2663
2925
|
);
|
|
2664
2926
|
}
|
|
2665
2927
|
function LanPinRow({ lanPin }) {
|
|
@@ -2669,22 +2931,17 @@ function LanPinRow({ lanPin }) {
|
|
|
2669
2931
|
(0, import_react.createElement)(
|
|
2670
2932
|
"label",
|
|
2671
2933
|
{ style: { display: "flex", gap: 8, alignItems: "center", cursor: "pointer" } },
|
|
2672
|
-
(0, import_react.createElement)("input", {
|
|
2673
|
-
type: "checkbox",
|
|
2674
|
-
checked: lanPin.enabled,
|
|
2675
|
-
onChange: (e) => lanPin.onToggle(e.target.checked),
|
|
2676
|
-
style: { width: 15, height: 15, accentColor: "var(--dsw-alias-button-primary-fill)" }
|
|
2677
|
-
}),
|
|
2934
|
+
(0, import_react.createElement)("input", { type: "checkbox", checked: lanPin.enabled, onChange: (e) => lanPin.onToggle(e.target.checked), style: { width: 15, height: 15, accentColor: t.primaryFill } }),
|
|
2678
2935
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "Require a PIN on the LAN")
|
|
2679
2936
|
),
|
|
2680
|
-
lanPin.enabled
|
|
2937
|
+
lanPin.enabled ? (0, import_react.createElement)(
|
|
2681
2938
|
"div",
|
|
2682
|
-
{ style: { display: "flex", gap: 8, alignItems: "center", marginTop: 8 } },
|
|
2939
|
+
{ style: { display: "flex", gap: 8, alignItems: "center", marginTop: 8, flexWrap: "wrap" } },
|
|
2683
2940
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "LAN PIN"),
|
|
2684
|
-
(0, import_react.createElement)("code", { style: {
|
|
2685
|
-
lanPin.show ? (0, import_react.createElement)("
|
|
2686
|
-
(0, import_react.createElement)("
|
|
2687
|
-
)
|
|
2941
|
+
(0, import_react.createElement)("code", { style: { fontFamily: "ui-monospace, monospace", fontSize: 15, letterSpacing: 2, color: t.labelPrimary } }, lanPin.show ? lanPin.pin ?? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"),
|
|
2942
|
+
lanPin.show ? (0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: lanPin.onHide }, "Hide") : (0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: lanPin.onShow }, "Show"),
|
|
2943
|
+
(0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: lanPin.onRotate }, "Rotate")
|
|
2944
|
+
) : null
|
|
2688
2945
|
);
|
|
2689
2946
|
}
|
|
2690
2947
|
function PublicAccess({ status, pin, showPin, onRevealPin, onHidePin, onRotatePin }) {
|
|
@@ -2696,27 +2953,30 @@ function PublicAccess({ status, pin, showPin, onRevealPin, onHidePin, onRotatePi
|
|
|
2696
2953
|
null,
|
|
2697
2954
|
(0, import_react.createElement)(
|
|
2698
2955
|
"div",
|
|
2699
|
-
{ style: { display: "flex", gap: 14, alignItems: "center", marginBottom: 12 } },
|
|
2956
|
+
{ "data-maestro-qr-row": "", style: { display: "flex", gap: 14, alignItems: "center", marginBottom: 12, flexWrap: "wrap" } },
|
|
2700
2957
|
(0, import_react.createElement)(QrImage, { url: status.publicUrl, size: 116 }),
|
|
2701
|
-
(0, import_react.createElement)(
|
|
2702
|
-
"div",
|
|
2703
|
-
null,
|
|
2704
|
-
(0, import_react.createElement)("div", { style: codeStyle }, status.publicUrl),
|
|
2705
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Works from anywhere; visitors enter the PIN below.")
|
|
2706
|
-
)
|
|
2958
|
+
(0, import_react.createElement)("div", null, (0, import_react.createElement)("div", { style: { fontFamily: "ui-monospace, monospace", fontSize: 12, color: t.labelPrimary, wordBreak: "break-all" } }, status.publicUrl), (0, import_react.createElement)("p", { style: captionStyle }, "Works from anywhere; visitors enter the PIN below."))
|
|
2707
2959
|
)
|
|
2708
2960
|
) : (0, import_react.createElement)("p", { style: captionStyle }, "Start the tunnel to get a public address."),
|
|
2709
2961
|
(0, import_react.createElement)(
|
|
2710
2962
|
"div",
|
|
2711
|
-
{ style: { display: "flex", gap: 8, alignItems: "center" } },
|
|
2963
|
+
{ style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" } },
|
|
2712
2964
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "Access PIN"),
|
|
2713
|
-
(0, import_react.createElement)("code", { style: {
|
|
2714
|
-
showPin ? (0, import_react.createElement)(
|
|
2715
|
-
(0, import_react.createElement)(
|
|
2965
|
+
(0, import_react.createElement)("code", { style: { fontFamily: "ui-monospace, monospace", fontSize: 15, letterSpacing: 2, color: t.labelPrimary } }, showPin && pin !== null ? pin : "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"),
|
|
2966
|
+
showPin ? (0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: onHidePin }, "Hide") : (0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: onRevealPin }, "Show"),
|
|
2967
|
+
(0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: onRotatePin }, "Rotate")
|
|
2716
2968
|
),
|
|
2717
2969
|
(0, import_react.createElement)("p", { style: captionStyle }, "Stays the same across tunnel and DSH restarts; use Rotate when you need a new PIN.")
|
|
2718
2970
|
);
|
|
2719
2971
|
}
|
|
2972
|
+
function NamedTunnelSetupNote() {
|
|
2973
|
+
return (0, import_react.createElement)(
|
|
2974
|
+
"div",
|
|
2975
|
+
{ style: { ...cardInsetStyle, marginTop: "12px" } },
|
|
2976
|
+
(0, import_react.createElement)("p", { style: { ...captionStyle, marginBottom: 4, fontWeight: 500, color: t.labelPrimary } }, "Named tunnel \u2014 one-time manual setup (requires your own Cloudflare account):"),
|
|
2977
|
+
(0, import_react.createElement)("ol", { style: { margin: "4px 0", paddingLeft: 20, fontSize: 12, color: t.labelSecondary, lineHeight: "18px" } }, (0, import_react.createElement)("li", null, "cloudflared tunnel login"), (0, import_react.createElement)("li", null, "cloudflared tunnel create dsh-maestro-webhook"), (0, import_react.createElement)("li", null, "cloudflared tunnel route dns dsh-maestro-webhook <your-hostname>"), (0, import_react.createElement)("li", null, "Paste the printed Tunnel ID, credentials file path and hostname below."))
|
|
2978
|
+
);
|
|
2979
|
+
}
|
|
2720
2980
|
function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
2721
2981
|
const [status, setStatus] = (0, import_react.useState)(null);
|
|
2722
2982
|
const [proxyStatus, setProxyStatus] = (0, import_react.useState)(null);
|
|
@@ -2729,11 +2989,141 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2729
2989
|
const [lanPinEnabled, setLanPinEnabled] = (0, import_react.useState)(false);
|
|
2730
2990
|
const [lanPin, setLanPin] = (0, import_react.useState)(null);
|
|
2731
2991
|
const [showLanPin, setShowLanPin] = (0, import_react.useState)(false);
|
|
2992
|
+
const [guard, setGuard] = (0, import_react.useState)({});
|
|
2993
|
+
const [patternsText, setPatternsText] = (0, import_react.useState)("");
|
|
2994
|
+
const [placeholdersText, setPlaceholdersText] = (0, import_react.useState)("");
|
|
2995
|
+
const [supervisorCfg, setSupervisorCfg] = (0, import_react.useState)({});
|
|
2996
|
+
const [notifierCfg, setNotifierCfg] = (0, import_react.useState)({});
|
|
2997
|
+
const [activeTab, setActiveTab] = (0, import_react.useState)("tunnel");
|
|
2998
|
+
(0, import_react.useEffect)(() => {
|
|
2999
|
+
const css = `
|
|
3000
|
+
/* Maestro nested tabs \u2014 market-like pill bar + mobile fixes */
|
|
3001
|
+
[data-maestro-tabs] { display:flex; gap:6px; overflow-x:auto; overflow-y:hidden; scrollbar-width:none; -webkit-overflow-scrolling:touch; overscroll-behavior-x:contain; touch-action:pan-x; padding-bottom:6px; margin-bottom:10px; border-bottom:1px solid var(--dsw-alias-border-l1, rgba(0,0,0,.08)); }
|
|
3002
|
+
[data-maestro-tabs]::-webkit-scrollbar { display:none; width:0; height:0; }
|
|
3003
|
+
[data-maestro-tab] { flex:none; height:32px; min-width:fit-content; padding:0 14px; border-radius:999px; border:1px solid var(--dsw-alias-border-l1, rgba(0,0,0,.12)); background:transparent; color:var(--dsw-alias-label-primary); font-size:13px; line-height:20px; white-space:nowrap; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; font-family:inherit; -webkit-tap-highlight-color:transparent; }
|
|
3004
|
+
[data-maestro-tab][data-active="true"] { background:var(--dsw-specific-sidebar-nav-item-active, #EBEEF2); border-color:var(--dsw-specific-sidebar-nav-item-active, #EBEEF2); color:var(--dsw-alias-label-primary); }
|
|
3005
|
+
[data-maestro-tab]:hover { background:var(--dsw-alias-interactive-bg-hover, rgba(0,0,0,.06)); }
|
|
3006
|
+
[data-maestro-tab][data-active="true"]:hover { background:var(--dsw-specific-sidebar-nav-item-active, #EBEEF2); }
|
|
3007
|
+
[data-maestro-tab]:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary, #4f6ef7); outline-offset:1px; }
|
|
3008
|
+
[data-maestro-panel] { width:100%; min-width:0; box-sizing:border-box; }
|
|
3009
|
+
/* label \u2192 input d\xEDnh nhau fix: flex column gap + full width */
|
|
3010
|
+
[data-maestro-panel] label { gap:6px !important; }
|
|
3011
|
+
[data-maestro-row]:last-child { border-bottom:none !important; }
|
|
3012
|
+
[data-maestro-panel] label > span { width:100% !important; box-sizing:border-box !important; }
|
|
3013
|
+
@media (max-width: 640px) {
|
|
3014
|
+
[data-maestro-settings-card] { max-width:100% !important; gap:6px !important; padding:0 2px !important; }
|
|
3015
|
+
[data-maestro-tabs] { gap:6px !important; padding:0 0 6px !important; margin:0 -2px 10px !important; }
|
|
3016
|
+
[data-maestro-tab] { height:32px !important; padding:0 12px !important; font-size:13px !important; }
|
|
3017
|
+
[data-maestro-mapping-row] { flex-direction:column !important; align-items:stretch !important; gap:8px !important; }
|
|
3018
|
+
[data-maestro-mapping-row] > * { flex:1 1 100% !important; width:100% !important; max-width:100% !important; }
|
|
3019
|
+
[data-maestro-qr-row] { flex-direction:column !important; align-items:flex-start !important; }
|
|
3020
|
+
[data-maestro-trigger-wrap] { max-width:100% !important; }
|
|
3021
|
+
[data-maestro-menu] { min-width:0 !important; max-width:calc(100vw - 32px) !important; left:0 !important; right:auto !important; }
|
|
3022
|
+
[data-maestro-panel] label { gap:8px !important; }
|
|
3023
|
+
div[data-maestro-row] { flex-direction:column !important; align-items:stretch !important; padding:12px 0 !important; }
|
|
3024
|
+
[data-maestro-row-text] { padding-right:0 !important; }
|
|
3025
|
+
[data-maestro-control] { width:100% !important; justify-content:flex-start !important; }
|
|
3026
|
+
[data-maestro-control] > span { width:100% !important; }
|
|
3027
|
+
[data-maestro-control] select { width:100% !important; }
|
|
3028
|
+
[data-maestro-project-grid] { grid-template-columns:1fr !important; }
|
|
3029
|
+
[data-maestro-project-card] { padding:10px !important; }
|
|
3030
|
+
[data-maestro-project-profile-row] { flex-direction:column !important; align-items:stretch !important; }
|
|
3031
|
+
[data-maestro-project-profile-row] > label { flex:1 1 100% !important; width:100% !important; }
|
|
3032
|
+
}
|
|
3033
|
+
@media (max-width: 390px) {
|
|
3034
|
+
[data-maestro-tab] { height:30px !important; padding:0 10px !important; font-size:12px !important; }
|
|
3035
|
+
}
|
|
3036
|
+
`;
|
|
3037
|
+
const tag = document.createElement("style");
|
|
3038
|
+
tag.dataset.plugin = "@ddtcorex/dsh-maestro-config";
|
|
3039
|
+
tag.dataset.pluginCss = "maestro/mobile-tabs.css";
|
|
3040
|
+
tag.textContent = css;
|
|
3041
|
+
document.head.appendChild(tag);
|
|
3042
|
+
return () => tag.remove();
|
|
3043
|
+
}, []);
|
|
2732
3044
|
const call = async (endpoint, payload) => {
|
|
2733
3045
|
const res = await rpcCall(endpoint, payload);
|
|
2734
3046
|
if (!res?.ok) throw new Error(res?.error?.message ?? "RPC failed");
|
|
2735
3047
|
return res.value;
|
|
2736
3048
|
};
|
|
3049
|
+
const unwrap = (res) => {
|
|
3050
|
+
if (res && typeof res === "object" && "ok" in res) {
|
|
3051
|
+
if (res.ok) return res.value;
|
|
3052
|
+
throw new Error(res.error?.message ?? "RPC failed");
|
|
3053
|
+
}
|
|
3054
|
+
return res;
|
|
3055
|
+
};
|
|
3056
|
+
const cfgGet = async (domain) => {
|
|
3057
|
+
if (!configRpcCall) throw new Error("config RPC not available");
|
|
3058
|
+
const res = await configRpcCall("get", { domain });
|
|
3059
|
+
return unwrap(res);
|
|
3060
|
+
};
|
|
3061
|
+
const cfgSet = async (domain, patch) => {
|
|
3062
|
+
if (!configRpcCall) throw new Error("config RPC not available");
|
|
3063
|
+
const res = await configRpcCall("set", { domain, patch });
|
|
3064
|
+
return unwrap(res);
|
|
3065
|
+
};
|
|
3066
|
+
const saveGuard = async (patch) => {
|
|
3067
|
+
setError(null);
|
|
3068
|
+
const next = { ...guard, ...patch };
|
|
3069
|
+
if (patch.gitProtection && guard.gitProtection) next.gitProtection = { ...guard.gitProtection, ...patch.gitProtection };
|
|
3070
|
+
setGuard(next);
|
|
3071
|
+
try {
|
|
3072
|
+
await cfgSet("guard", patch);
|
|
3073
|
+
} catch (e) {
|
|
3074
|
+
setError(e.message ?? String(e));
|
|
3075
|
+
}
|
|
3076
|
+
};
|
|
3077
|
+
const commitBlacklistPatterns = async (text) => {
|
|
3078
|
+
const patterns = text.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
3079
|
+
setError(null);
|
|
3080
|
+
try {
|
|
3081
|
+
await cfgSet("guardBlacklist", { patterns });
|
|
3082
|
+
} catch (e) {
|
|
3083
|
+
setError(e.message ?? String(e));
|
|
3084
|
+
}
|
|
3085
|
+
};
|
|
3086
|
+
const commitPlaceholders = async () => {
|
|
3087
|
+
setError(null);
|
|
3088
|
+
let obj = {};
|
|
3089
|
+
try {
|
|
3090
|
+
obj = placeholdersText.trim() ? JSON.parse(placeholdersText) : {};
|
|
3091
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) throw new Error("placeholders must be JSON object");
|
|
3092
|
+
} catch (e) {
|
|
3093
|
+
setError(`placeholders JSON invalid: ${e.message ?? String(e)}`);
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
try {
|
|
3097
|
+
await cfgSet("guardBlacklist", { placeholders: obj });
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
setError(e.message ?? String(e));
|
|
3100
|
+
}
|
|
3101
|
+
};
|
|
3102
|
+
const saveSupervisorCfg = async (patch) => {
|
|
3103
|
+
setError(null);
|
|
3104
|
+
setSupervisorCfg((prev) => ({ ...prev, ...patch }));
|
|
3105
|
+
try {
|
|
3106
|
+
await cfgSet("supervisor", patch);
|
|
3107
|
+
} catch (e) {
|
|
3108
|
+
setError(e.message ?? String(e));
|
|
3109
|
+
}
|
|
3110
|
+
};
|
|
3111
|
+
const saveNotifierCfg = async (patch) => {
|
|
3112
|
+
setError(null);
|
|
3113
|
+
setNotifierCfg((prev) => {
|
|
3114
|
+
const next = { ...prev };
|
|
3115
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
3116
|
+
if (k === "telegram" && typeof v === "object" && v !== null) next.telegram = { ...prev.telegram ?? {}, ...v };
|
|
3117
|
+
else next[k] = v;
|
|
3118
|
+
}
|
|
3119
|
+
return next;
|
|
3120
|
+
});
|
|
3121
|
+
try {
|
|
3122
|
+
await cfgSet("notifier", patch);
|
|
3123
|
+
} catch (e) {
|
|
3124
|
+
setError(e.message ?? String(e));
|
|
3125
|
+
}
|
|
3126
|
+
};
|
|
2737
3127
|
const refresh = async () => {
|
|
2738
3128
|
try {
|
|
2739
3129
|
setStatus(await call(MAESTRO_ENDPOINTS.status, {}));
|
|
@@ -2749,9 +3139,17 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2749
3139
|
});
|
|
2750
3140
|
if (configRpcCall) {
|
|
2751
3141
|
configRpcCall("get", { domain: "supervisor" }).then((res) => {
|
|
2752
|
-
if (res?.ok && res.value?.model) {
|
|
2753
|
-
|
|
2754
|
-
|
|
3142
|
+
if (res?.ok && res.value?.model) setConfig((prev) => ({ ...prev, supervisorModel: res.value.model }));
|
|
3143
|
+
}).catch(() => {
|
|
3144
|
+
});
|
|
3145
|
+
Promise.all([cfgGet("guard").catch(() => ({})), cfgGet("guardBlacklist").catch(() => ({ patterns: [], placeholders: {} })), cfgGet("supervisor").catch(() => ({})), cfgGet("notifier").catch(() => ({}))]).then(([g, bl, sup, not]) => {
|
|
3146
|
+
setGuard(g ?? {});
|
|
3147
|
+
const pats = Array.isArray(bl?.patterns) ? bl.patterns : [];
|
|
3148
|
+
const ph = bl?.placeholders && typeof bl.placeholders === "object" ? bl.placeholders : {};
|
|
3149
|
+
setPatternsText(pats.join("\n"));
|
|
3150
|
+
setPlaceholdersText(JSON.stringify(ph, null, 2));
|
|
3151
|
+
setSupervisorCfg(sup ?? {});
|
|
3152
|
+
setNotifierCfg(not ?? {});
|
|
2755
3153
|
}).catch(() => {
|
|
2756
3154
|
});
|
|
2757
3155
|
}
|
|
@@ -2765,8 +3163,8 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2765
3163
|
}, []);
|
|
2766
3164
|
(0, import_react.useEffect)(() => {
|
|
2767
3165
|
refresh();
|
|
2768
|
-
const
|
|
2769
|
-
return () => clearInterval(
|
|
3166
|
+
const t2 = setInterval(refresh, 3e3);
|
|
3167
|
+
return () => clearInterval(t2);
|
|
2770
3168
|
}, []);
|
|
2771
3169
|
const revealPin = async () => {
|
|
2772
3170
|
if (pin === null) {
|
|
@@ -2856,7 +3254,7 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2856
3254
|
try {
|
|
2857
3255
|
const res = await configRpcCall("set", { domain: "supervisor", patch: { model: value } });
|
|
2858
3256
|
if (res?.ok) return;
|
|
2859
|
-
} catch
|
|
3257
|
+
} catch {
|
|
2860
3258
|
}
|
|
2861
3259
|
}
|
|
2862
3260
|
try {
|
|
@@ -2865,150 +3263,131 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2865
3263
|
setError(err.message);
|
|
2866
3264
|
}
|
|
2867
3265
|
};
|
|
2868
|
-
|
|
2869
|
-
"
|
|
2870
|
-
{
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
config.tunnelMode === "named" && (0, import_react.createElement)(
|
|
3266
|
+
const TABS = [
|
|
3267
|
+
{ id: "tunnel", label: "Tunnel" },
|
|
3268
|
+
{ id: "notify", label: "Notify" },
|
|
3269
|
+
{ id: "gitlab", label: "GitLab" },
|
|
3270
|
+
{ id: "review", label: "Review" },
|
|
3271
|
+
{ id: "guard", label: "Guard" },
|
|
3272
|
+
{ id: "blacklist", label: "Blacklist" },
|
|
3273
|
+
{ id: "supervisor", label: "Supervisor" },
|
|
3274
|
+
{ id: "notifier", label: "Notifier" }
|
|
3275
|
+
];
|
|
3276
|
+
const tabContents = {
|
|
3277
|
+
tunnel: (0, import_react.createElement)(
|
|
2881
3278
|
"div",
|
|
2882
|
-
|
|
2883
|
-
(0, import_react.createElement)("
|
|
2884
|
-
|
|
2885
|
-
(0, import_react.createElement)(
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
3279
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3280
|
+
(0, import_react.createElement)(SettingRow, { title: "Tunnel mode", description: "Quick = ephemeral URL, Named = stable URL with Cloudflare setup.", control: (0, import_react.createElement)("select", { value: config.tunnelMode, onChange: (e) => saveField("tunnelMode", e.target.value), style: { height: 36, padding: "0 12px", border: `1px solid ${t.borderL2}`, borderRadius: 18, background: "var(--dsw-alias-bg-module-platform, #F5F6F7)", color: t.labelPrimary, font: "inherit", fontSize: 13 } }, (0, import_react.createElement)("option", { value: "quick" }, "Quick"), (0, import_react.createElement)("option", { value: "named" }, "Named")) }),
|
|
3281
|
+
config.tunnelMode === "named" ? (0, import_react.createElement)(NamedTunnelSetupNote, null) : null,
|
|
3282
|
+
config.tunnelMode === "named" ? (0, import_react.createElement)(
|
|
3283
|
+
"div",
|
|
3284
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3285
|
+
(0, import_react.createElement)(SettingRow, { title: "Tunnel ID", description: "Cloudflare tunnel ID.", control: (0, import_react.createElement)(FieldInput, { placeholder: "Tunnel ID", value: config.tunnelId ?? "", onChange: (e) => saveField("tunnelId", e.target.value), style: { width: 260 } }) }),
|
|
3286
|
+
(0, import_react.createElement)(SettingRow, { title: "Credentials file", description: "Path to tunnel credentials JSON.", control: (0, import_react.createElement)(FieldInput, { placeholder: "~/.cloudflared/<id>.json", value: config.tunnelCredentialsFile ?? "", onChange: (e) => saveField("tunnelCredentialsFile", e.target.value), style: { width: 260 } }) }),
|
|
3287
|
+
(0, import_react.createElement)(SettingRow, { title: "Hostname", description: "Public hostname for the tunnel.", control: (0, import_react.createElement)(FieldInput, { placeholder: "dsh.example.com", value: config.tunnelHostname ?? "", onChange: (e) => saveField("tunnelHostname", e.target.value), style: { width: 260 } }) })
|
|
3288
|
+
) : null,
|
|
3289
|
+
(0, import_react.createElement)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", padding: "12px 0", borderBottom: `1px solid ${t.borderL2}` } }, status?.running ? (0, import_react.createElement)(Button, { variant: "outline", size: "md", disabled: busy, onClick: stopTunnel }, "Stop tunnel") : (0, import_react.createElement)(Button, { variant: "primary", size: "md", disabled: busy, onClick: startTunnel }, "Start tunnel")),
|
|
3290
|
+
(0, import_react.createElement)("div", { style: { ...cardInsetStyle, marginTop: "12px" } }, (0, import_react.createElement)("div", { style: { fontSize: 13, fontWeight: 600, color: t.labelPrimary } }, "Remote access \u2014 LAN"), (0, import_react.createElement)(LanAccess, { proxyStatus, lanPin: lanPinEnabled === null ? null : { enabled: lanPinEnabled, pin: lanPin, show: showLanPin, onShow: revealLanPin, onHide: () => setShowLanPin(false), onRotate: rotateLanPin, onToggle: toggleLanPin } })),
|
|
3291
|
+
(0, import_react.createElement)("div", { style: { ...cardInsetStyle, marginTop: "12px" } }, (0, import_react.createElement)("div", { style: { fontSize: 13, fontWeight: 600, color: t.labelPrimary } }, "Public access"), (0, import_react.createElement)(PublicAccess, { status, pin, showPin, onRevealPin: revealPin, onHidePin: () => setShowPin(false), onRotatePin: rotatePin }))
|
|
2889
3292
|
),
|
|
2890
|
-
(0, import_react.createElement)(
|
|
3293
|
+
notify: (0, import_react.createElement)(
|
|
2891
3294
|
"div",
|
|
2892
|
-
{ style: {
|
|
2893
|
-
|
|
3295
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3296
|
+
(0, import_react.createElement)("div", { style: { padding: "12px 0", borderBottom: `1px solid ${t.borderL2}` } }, (0, import_react.createElement)("p", { style: captionStyle }, "Sends one protected startup update with the current public-access PIN to a single chat. Leave either credential blank to disable.")),
|
|
3297
|
+
(0, import_react.createElement)(SettingRow, { title: "Bot token", description: "Telegram bot token from @BotFather.", control: (0, import_react.createElement)("div", { style: { display: "flex", gap: 8, alignItems: "center" } }, (0, import_react.createElement)(FieldInput, { placeholder: "123456:ABC-DEF...", type: "password", autoComplete: "off", value: config.hasTelegramBotToken ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "", onChange: (e) => saveField("telegramBotToken", e.target.value), style: { width: 220 } }), config.hasTelegramBotToken ? (0, import_react.createElement)(Button, { variant: "outline", size: "md", onClick: () => saveField("telegramBotToken", "") }, "Clear") : null) }),
|
|
3298
|
+
(0, import_react.createElement)(SettingRow, { title: "Chat ID", description: "Target chat, e.g. -1001234567890.", control: (0, import_react.createElement)(FieldInput, { placeholder: "-1001234567890", value: config.telegramChatId ?? "", onChange: (e) => saveField("telegramChatId", e.target.value), style: { width: 220 } }) }),
|
|
3299
|
+
(0, import_react.createElement)(ToggleRow, { title: "Also notify about reviews", description: "One message per review run with its outcome.", checked: config.telegramReviewNotifications === true, onChange: (v) => saveField("telegramReviewNotifications", v) })
|
|
2894
3300
|
),
|
|
2895
|
-
(0, import_react.createElement)(
|
|
3301
|
+
gitlab: (0, import_react.createElement)(
|
|
2896
3302
|
"div",
|
|
2897
|
-
{ style:
|
|
2898
|
-
(0, import_react.createElement)("
|
|
2899
|
-
(0, import_react.createElement)(
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
onToggle: toggleLanPin
|
|
2909
|
-
}
|
|
2910
|
-
})
|
|
3303
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3304
|
+
(0, import_react.createElement)(SettingRow, { title: "GitLab base URL", description: "e.g. https://gitlab.example.com", control: (0, import_react.createElement)(FieldInput, { placeholder: "https://gitlab.example.com", value: config.gitlabBaseUrl ?? "", onChange: (e) => saveField("gitlabBaseUrl", e.target.value), style: { width: 260 } }) }),
|
|
3305
|
+
(0, import_react.createElement)(SettingRow, { title: "GitLab token", description: "Personal access token with api scope.", control: (0, import_react.createElement)("div", { style: { display: "flex", gap: 8, alignItems: "center" } }, (0, import_react.createElement)(FieldInput, { type: "password", autoComplete: "off", value: config.hasGitlabToken ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "", placeholder: "GitLab token", onChange: (e) => saveField("gitlabToken", e.target.value), style: { width: 200 } }), config.hasGitlabToken ? (0, import_react.createElement)(Button, { variant: "outline", size: "md", onClick: () => saveField("gitlabToken", "") }, "Clear") : null) }),
|
|
3306
|
+
(0, import_react.createElement)(SettingRow, { title: "Bot username", description: "Username of the bot that posts reviews.", control: (0, import_react.createElement)(FieldInput, { placeholder: "maestro-bot", value: config.botUsername ?? "", onChange: (e) => saveField("botUsername", e.target.value), style: { width: 220 } }) }),
|
|
3307
|
+
(0, import_react.createElement)(SettingRow, { title: "Webhook secret", description: "Secret token for GitLab webhooks.", control: (0, import_react.createElement)("div", { style: { display: "flex", gap: 8, alignItems: "center" } }, (0, import_react.createElement)(FieldInput, { type: "password", autoComplete: "off", value: config.hasWebhookSecret ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "", placeholder: "Webhook secret", onChange: (e) => saveField("webhookSecret", e.target.value), style: { width: 200 } }), (0, import_react.createElement)(Button, { variant: "outline", size: "md", onClick: () => saveField("webhookSecret", generateWebhookSecret()) }, "Generate")) }),
|
|
3308
|
+
(0, import_react.createElement)(
|
|
3309
|
+
"div",
|
|
3310
|
+
{ style: { padding: "16px 0", display: "flex", flexDirection: "column", gap: 6 } },
|
|
3311
|
+
(0, import_react.createElement)("p", { style: captionStyle }, "In GitLab: Settings \u2192 Webhooks, Secret token = this value, enable Merge request events. Webhook URL:"),
|
|
3312
|
+
(0, import_react.createElement)("div", { style: { fontFamily: "ui-monospace, monospace", fontSize: 12, color: t.labelPrimary, wordBreak: "break-all", padding: "10px 12px", borderRadius: 8, background: t.bgLayer3, border: `1px solid ${t.borderL2}`, overflowWrap: "anywhere" } }, gitlabWebhookUrl(config.tunnelHostname))
|
|
3313
|
+
)
|
|
2911
3314
|
),
|
|
2912
|
-
(0, import_react.createElement)(
|
|
3315
|
+
review: (0, import_react.createElement)(
|
|
2913
3316
|
"div",
|
|
2914
|
-
{ style:
|
|
2915
|
-
(0, import_react.createElement)(
|
|
2916
|
-
(0, import_react.createElement)(
|
|
3317
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3318
|
+
(0, import_react.createElement)(ToggleRow, { title: "Re-review on push", description: "When new commits are pushed, trigger an automatic re-review.", checked: config.autoRereviewOnPush === true, onChange: (v) => saveField("autoRereviewOnPush", v) }),
|
|
3319
|
+
(0, import_react.createElement)(SettingRow, { title: "Global review model", description: "Model for automated reviews. Empty = DSH default.", control: (0, import_react.createElement)(ReviewModelSelector, { value: config.reviewModel ?? null, catalog, fallbackValue: catalog?.current ?? null, fallbackLabel: "Use DSH default", onChange: (v) => saveField("reviewModel", v), label: null }) }),
|
|
3320
|
+
(0, import_react.createElement)(SettingRow, { title: "Supervisor model", description: "Model for auto-fixing DSH Web crashes.", control: (0, import_react.createElement)(ReviewModelSelector, { value: config.supervisorModel ?? null, catalog, fallbackValue: catalog?.current ?? null, fallbackLabel: "Use DSH default", onChange: (v) => saveField("supervisorModel", v), label: null }) }),
|
|
3321
|
+
(0, import_react.createElement)(ProjectMappingsEditor, { mappings: config.projectMappings ?? [], onChange: (mappings) => saveField("projectMappings", mappings), catalog, globalReviewModel: config.reviewModel ?? null })
|
|
2917
3322
|
),
|
|
2918
|
-
(0, import_react.createElement)(
|
|
3323
|
+
guard: (0, import_react.createElement)(
|
|
2919
3324
|
"div",
|
|
2920
|
-
{ style:
|
|
2921
|
-
(0, import_react.createElement)(
|
|
2922
|
-
(0, import_react.createElement)(
|
|
2923
|
-
(0, import_react.createElement)(
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
hasSaved: config.hasTelegramBotToken,
|
|
2927
|
-
onSave: (value) => saveField("telegramBotToken", value)
|
|
2928
|
-
}),
|
|
2929
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "Chat ID"),
|
|
2930
|
-
(0, import_react.createElement)("input", { placeholder: "-1001234567890", autoComplete: "off", style: inputStyle, value: config.telegramChatId ?? "", onChange: (e) => saveField("telegramChatId", e.target.value) }),
|
|
2931
|
-
(0, import_react.createElement)(ToggleField, {
|
|
2932
|
-
label: "Also notify about finished reviews",
|
|
2933
|
-
caption: "One message per review run with its outcome and a short summary.",
|
|
2934
|
-
checked: config.telegramReviewNotifications,
|
|
2935
|
-
onChange: (checked) => saveField("telegramReviewNotifications", checked)
|
|
2936
|
-
}),
|
|
2937
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Leave either credential blank to disable notifications. Telegram delivery failures never prevent DSH from starting.")
|
|
3325
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3326
|
+
(0, import_react.createElement)(ToggleRow, { title: "Block publish commands", description: "Prevent publish-related commands when enabled.", checked: guard.publishBlocked === true, onChange: (v) => saveGuard({ publishBlocked: v }) }),
|
|
3327
|
+
(0, import_react.createElement)(ToggleRow, { title: "Protect git branches", description: "Block direct pushes to protected branches.", checked: guard.gitProtection?.enabled === true, onChange: (v) => saveGuard({ gitProtection: { enabled: v, branches: guard.gitProtection?.branches ?? ["master", "main"] } }) }),
|
|
3328
|
+
(0, import_react.createElement)(SettingRow, { title: "Protected branches", description: "Comma-separated list, e.g. master, main.", control: (0, import_react.createElement)(FieldInput, { value: (guard.gitProtection?.branches ?? ["master", "main"]).join(", "), placeholder: "master, main", onChange: (e) => saveGuard({ gitProtection: { enabled: guard.gitProtection?.enabled ?? true, branches: e.target.value.split(",").map((s) => s.trim()).filter(Boolean) } }), style: { width: 260 } }) }),
|
|
3329
|
+
(0, import_react.createElement)(ToggleRow, { title: "Contain working directory", description: "Restrict file operations to the session working directory.", checked: guard.cwdContainment === true, onChange: (v) => saveGuard({ cwdContainment: v }) }),
|
|
3330
|
+
(0, import_react.createElement)(SettingRow, { title: "Credential file paths", description: "Comma-separated paths to credential files.", control: (0, import_react.createElement)(FieldInput, { value: (guard.credentialPaths ?? []).join(", "), placeholder: "~/.config/credentials.yaml", onChange: (e) => saveGuard({ credentialPaths: e.target.value.split(",").map((s) => s.trim()).filter(Boolean) }), style: { width: 260 } }) })
|
|
2938
3331
|
),
|
|
2939
|
-
(0, import_react.createElement)(
|
|
3332
|
+
blacklist: (0, import_react.createElement)(
|
|
2940
3333
|
"div",
|
|
2941
|
-
{ style:
|
|
2942
|
-
(0, import_react.createElement)(
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
placeholder: "
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "In GitLab: Settings \u2192 Webhooks, set Secret token to this value and enable Merge request events."),
|
|
2961
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Webhook URL:"),
|
|
2962
|
-
(0, import_react.createElement)("code", { style: codeStyle }, gitlabWebhookUrl(config.tunnelHostname)),
|
|
2963
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Overrides MAESTRO_GITLAB_WEBHOOK_SECRET immediately, no restart needed.")
|
|
3334
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3335
|
+
(0, import_react.createElement)(
|
|
3336
|
+
"div",
|
|
3337
|
+
{ style: { ...rowStyle, flexDirection: "column", alignItems: "stretch", gap: 8 } },
|
|
3338
|
+
(0, import_react.createElement)("div", { style: rowTitleStyle }, "Blacklist patterns"),
|
|
3339
|
+
(0, import_react.createElement)("div", { style: rowDescStyle }, "One pattern per line. Matching files are blocked from commit."),
|
|
3340
|
+
(0, import_react.createElement)(TextareaField, { value: patternsText, placeholder: "example-project\nacme-shop", onChange: (e) => setPatternsText(e.target.value), onBlur: (e) => commitBlacklistPatterns(e.target.value) })
|
|
3341
|
+
),
|
|
3342
|
+
(0, import_react.createElement)(
|
|
3343
|
+
"div",
|
|
3344
|
+
{ style: { ...rowStyle, flexDirection: "column", alignItems: "stretch", gap: 8, borderBottom: "none" } },
|
|
3345
|
+
(0, import_react.createElement)("div", { style: rowTitleStyle }, "Placeholder mappings"),
|
|
3346
|
+
(0, import_react.createElement)("div", { style: rowDescStyle }, "JSON object mapping blocked patterns to placeholder suggestions."),
|
|
3347
|
+
(0, import_react.createElement)(TextareaField, { value: placeholdersText, placeholder: '{"example-project":"my-project"}', onChange: (e) => setPlaceholdersText(e.target.value), onBlur: () => commitPlaceholders(), style: { minHeight: 80 } }),
|
|
3348
|
+
(0, import_react.createElement)("div", { style: { marginTop: 8 } }, (0, import_react.createElement)(Button, { variant: "outline", size: "sm", onClick: () => {
|
|
3349
|
+
commitBlacklistPatterns(patternsText);
|
|
3350
|
+
commitPlaceholders();
|
|
3351
|
+
} }, "Save Blacklist"))
|
|
3352
|
+
)
|
|
2964
3353
|
),
|
|
2965
|
-
(0, import_react.createElement)(
|
|
3354
|
+
supervisor: (0, import_react.createElement)(
|
|
2966
3355
|
"div",
|
|
2967
|
-
{ style:
|
|
2968
|
-
(0, import_react.createElement)("
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3356
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3357
|
+
(0, import_react.createElement)(SettingRow, { title: "Check interval", description: "Milliseconds between supervisor checks. Default 5000.", control: (0, import_react.createElement)(FieldInput, { type: "number", value: supervisorCfg.intervalMs ?? "", placeholder: "5000", onChange: (e) => {
|
|
3358
|
+
const v = e.target.value === "" ? void 0 : Number(e.target.value);
|
|
3359
|
+
saveSupervisorCfg({ intervalMs: v });
|
|
3360
|
+
}, style: { width: 160 } }) }),
|
|
3361
|
+
(0, import_react.createElement)(SettingRow, { title: "Down threshold", description: "Consecutive failures before marking a session as down.", control: (0, import_react.createElement)(FieldInput, { type: "number", value: supervisorCfg.downThreshold ?? "", placeholder: "3", onChange: (e) => {
|
|
3362
|
+
const v = e.target.value === "" ? void 0 : Number(e.target.value);
|
|
3363
|
+
saveSupervisorCfg({ downThreshold: v });
|
|
3364
|
+
}, style: { width: 160 } }) }),
|
|
3365
|
+
(0, import_react.createElement)(ToggleRow, { title: "Auto-resume sessions", description: "Automatically resume sessions marked as down.", checked: supervisorCfg.autoResumeEnabled === true, onChange: (v) => saveSupervisorCfg({ autoResumeEnabled: v }) })
|
|
2976
3366
|
),
|
|
2977
|
-
(0, import_react.createElement)(
|
|
3367
|
+
notifier: (0, import_react.createElement)(
|
|
2978
3368
|
"div",
|
|
2979
|
-
{ style:
|
|
2980
|
-
(0, import_react.createElement)("
|
|
2981
|
-
(0, import_react.createElement)(
|
|
2982
|
-
(0, import_react.createElement)(
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
label: "Global review model"
|
|
2989
|
-
})
|
|
2990
|
-
),
|
|
3369
|
+
{ style: { display: "flex", flexDirection: "column" } },
|
|
3370
|
+
(0, import_react.createElement)(SettingRow, { title: "Bot token", description: "Telegram bot token from @BotFather.", control: (0, import_react.createElement)(FieldInput, { type: "password", autoComplete: "off", value: notifierCfg.telegram?.botToken ?? "", placeholder: "123456:ABC-DEF...", onChange: (e) => saveNotifierCfg({ telegram: { botToken: e.target.value } }), style: { width: 260 } }) }),
|
|
3371
|
+
(0, import_react.createElement)(SettingRow, { title: "Chat ID", description: "Target chat, e.g. -1001234567890.", control: (0, import_react.createElement)(FieldInput, { value: notifierCfg.telegram?.chatId ?? "", placeholder: "-1001234567890", onChange: (e) => saveNotifierCfg({ telegram: { chatId: e.target.value } }), style: { width: 260 } }) }),
|
|
3372
|
+
(0, import_react.createElement)(ToggleRow, { title: "Review notifications", description: "Also notify about finished reviews.", checked: notifierCfg.telegram?.reviewNotifications === true || notifierCfg.policy?.reviewNotifications === true, onChange: (v) => saveNotifierCfg({ telegram: { reviewNotifications: v } }) })
|
|
3373
|
+
)
|
|
3374
|
+
};
|
|
3375
|
+
return (0, import_react.createElement)(
|
|
3376
|
+
"div",
|
|
3377
|
+
{ "data-maestro-settings-card": "", style: { display: "flex", flexDirection: "column", gap: 8, width: "100%", maxWidth: 640, minWidth: 0, boxSizing: "border-box" } },
|
|
2991
3378
|
(0, import_react.createElement)(
|
|
2992
3379
|
"div",
|
|
2993
|
-
{ style:
|
|
2994
|
-
(0, import_react.createElement)("
|
|
2995
|
-
(0, import_react.createElement)("
|
|
2996
|
-
(0, import_react.createElement)(ReviewModelSelector, {
|
|
2997
|
-
value: config.supervisorModel ?? null,
|
|
2998
|
-
catalog,
|
|
2999
|
-
fallbackValue: catalog?.current ?? null,
|
|
3000
|
-
fallbackLabel: "Use DSH default",
|
|
3001
|
-
onChange: (v) => saveField("supervisorModel", v),
|
|
3002
|
-
label: "Supervisor model"
|
|
3003
|
-
})
|
|
3380
|
+
{ style: { padding: "2px 2px 8px" } },
|
|
3381
|
+
(0, import_react.createElement)("div", { style: { fontSize: 15, fontWeight: 600, color: t.labelPrimary, lineHeight: "22px" } }, "Maestro"),
|
|
3382
|
+
(0, import_react.createElement)("div", { style: { fontSize: 12, color: t.labelSecondary, lineHeight: "16px", marginTop: 2 } }, "Tunnel, access, review & guard \u2014 all via the shared Maestro store. Uses the same tokens and primitives as DSH settings.")
|
|
3004
3383
|
),
|
|
3005
3384
|
(0, import_react.createElement)(
|
|
3006
3385
|
"div",
|
|
3007
|
-
{
|
|
3008
|
-
(0, import_react.createElement)("
|
|
3009
|
-
(0, import_react.createElement)(ProjectMappingsEditor, { mappings: config.projectMappings ?? [], onChange: (mappings) => saveField("projectMappings", mappings), catalog, globalReviewModel: config.reviewModel ?? null })
|
|
3386
|
+
{ "data-maestro-tabs": "", role: "tablist", "aria-label": "Maestro settings sections" },
|
|
3387
|
+
...TABS.map((tab) => (0, import_react.createElement)("button", { key: tab.id, "data-maestro-tab": "", "data-active": String(activeTab === tab.id), role: "tab", "aria-selected": activeTab === tab.id, onClick: () => setActiveTab(tab.id) }, tab.label))
|
|
3010
3388
|
),
|
|
3011
|
-
|
|
3389
|
+
(0, import_react.createElement)("div", { "data-maestro-panel": activeTab, style: { display: "flex", flexDirection: "column", gap: 10, minWidth: 0 } }, tabContents[activeTab]),
|
|
3390
|
+
error ? (0, import_react.createElement)("p", { style: { color: t.stateError, fontSize: 12, margin: "8px 0 0", padding: "8px 10px", borderRadius: 8, background: "color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent)", border: `1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 30%, transparent)` } }, error) : null
|
|
3012
3391
|
);
|
|
3013
3392
|
}
|
|
3014
3393
|
|
|
@@ -3049,9 +3428,9 @@ function registerSettingsNavIcon(label, root) {
|
|
|
3049
3428
|
}
|
|
3050
3429
|
|
|
3051
3430
|
// src/client/index.tsx
|
|
3052
|
-
var
|
|
3431
|
+
var SETTINGS_NAV_CSS = `
|
|
3053
3432
|
|
|
3054
|
-
/* maestro: replace the settings-nav fallback gear with the
|
|
3433
|
+
/* maestro: replace the settings-nav fallback gear with the Maestro M-logo glyph */
|
|
3055
3434
|
[${SETTINGS_NAV_MARKER}] > svg:first-child {
|
|
3056
3435
|
display: none;
|
|
3057
3436
|
}
|
|
@@ -3062,15 +3441,16 @@ var SETTINGS_NAV_CSS2 = `
|
|
|
3062
3441
|
width: 16px;
|
|
3063
3442
|
height: 16px;
|
|
3064
3443
|
background: currentColor;
|
|
3065
|
-
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='
|
|
3066
|
-
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='
|
|
3444
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 11 L5 4 L8 9 L11 4 L14 11'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
3445
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 11 L5 4 L8 9 L11 4 L14 11'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
3067
3446
|
}
|
|
3068
3447
|
`;
|
|
3448
|
+
var inject = ["slots", "connection"];
|
|
3069
3449
|
function installNavIconStyle() {
|
|
3070
3450
|
const tag = document.createElement("style");
|
|
3071
3451
|
tag.dataset.plugin = "@ddtcorex/dsh-maestro-config";
|
|
3072
3452
|
tag.dataset.pluginCss = "maestro/settings-nav.css";
|
|
3073
|
-
tag.textContent =
|
|
3453
|
+
tag.textContent = SETTINGS_NAV_CSS;
|
|
3074
3454
|
document.head.appendChild(tag);
|
|
3075
3455
|
return () => {
|
|
3076
3456
|
document.querySelector('style[data-plugin-css="maestro/settings-nav.css"]')?.remove();
|