@ddtcorex/dsh-maestro-config 0.1.2 → 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
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;
|
|
@@ -2122,7 +2122,7 @@ __export(index_exports, {
|
|
|
2122
2122
|
});
|
|
2123
2123
|
module.exports = __toCommonJS(index_exports);
|
|
2124
2124
|
|
|
2125
|
-
// src/client/
|
|
2125
|
+
// src/client/MaestroSettings.tsx
|
|
2126
2126
|
var import_react = require("react");
|
|
2127
2127
|
var import_qrcode = __toESM(require_browser(), 1);
|
|
2128
2128
|
|
|
@@ -2156,95 +2156,252 @@ function gitlabWebhookUrl(hostname) {
|
|
|
2156
2156
|
return `https://${authority}/hooks/gitlab-mr`;
|
|
2157
2157
|
}
|
|
2158
2158
|
|
|
2159
|
-
// src/client/
|
|
2160
|
-
var
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
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)"
|
|
2171
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
|
+
}
|
|
2172
2320
|
var fieldLabelStyle = {
|
|
2173
|
-
display: "
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
padding: "0 14px",
|
|
2182
|
-
borderRadius: 16,
|
|
2183
|
-
border: "1px solid var(--dsw-alias-border-l2)",
|
|
2184
|
-
background: "transparent",
|
|
2185
|
-
color: "var(--dsw-alias-label-primary)",
|
|
2186
|
-
font: "inherit",
|
|
2187
|
-
fontSize: 13,
|
|
2188
|
-
cursor: "pointer",
|
|
2189
|
-
flex: "none"
|
|
2190
|
-
};
|
|
2191
|
-
var primaryButtonStyle = {
|
|
2192
|
-
...secondaryButtonStyle,
|
|
2193
|
-
border: "none",
|
|
2194
|
-
background: "var(--dsw-alias-button-primary-fill)",
|
|
2195
|
-
color: "var(--dsw-alias-label-primary-foreground)"
|
|
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"
|
|
2196
2329
|
};
|
|
2197
2330
|
var captionStyle = {
|
|
2198
|
-
fontSize:
|
|
2199
|
-
lineHeight:
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
};
|
|
2203
|
-
var sectionStyle = {
|
|
2204
|
-
marginTop: 20,
|
|
2205
|
-
paddingTop: 16,
|
|
2206
|
-
borderTop: "1px solid var(--dsw-alias-border-l2)"
|
|
2331
|
+
fontSize: "12px",
|
|
2332
|
+
lineHeight: "16px",
|
|
2333
|
+
color: t.labelSecondary,
|
|
2334
|
+
margin: "4px 0"
|
|
2207
2335
|
};
|
|
2208
|
-
var
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
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
|
|
2213
2344
|
};
|
|
2214
|
-
var
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
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"
|
|
2218
2352
|
};
|
|
2219
|
-
var
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2353
|
+
var rowTextStyle = {
|
|
2354
|
+
flex: "1",
|
|
2355
|
+
minWidth: "0",
|
|
2356
|
+
display: "flex",
|
|
2357
|
+
flexDirection: "column",
|
|
2358
|
+
gap: "4px",
|
|
2359
|
+
paddingRight: "48px"
|
|
2224
2360
|
};
|
|
2225
|
-
var
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2361
|
+
var rowTitleStyle = {
|
|
2362
|
+
fontSize: "14px",
|
|
2363
|
+
fontWeight: "400",
|
|
2364
|
+
lineHeight: "22px",
|
|
2365
|
+
color: t.labelPrimary
|
|
2230
2366
|
};
|
|
2231
|
-
var
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2367
|
+
var rowDescStyle = {
|
|
2368
|
+
fontSize: "12px",
|
|
2369
|
+
fontWeight: "400",
|
|
2370
|
+
lineHeight: "18px",
|
|
2371
|
+
color: t.labelTertiary
|
|
2236
2372
|
};
|
|
2237
|
-
var
|
|
2238
|
-
|
|
2373
|
+
var pillSelectorStyle = {
|
|
2374
|
+
display: "inline-flex",
|
|
2375
|
+
alignItems: "center",
|
|
2376
|
+
gap: "12px",
|
|
2377
|
+
height: "36px",
|
|
2378
|
+
padding: "0 14px",
|
|
2239
2379
|
border: "none",
|
|
2240
|
-
|
|
2241
|
-
background: "
|
|
2242
|
-
color: active ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-secondary)",
|
|
2380
|
+
borderRadius: "18px",
|
|
2381
|
+
background: "var(--dsw-alias-bg-module-platform, #F5F6F7)",
|
|
2243
2382
|
font: "inherit",
|
|
2244
|
-
fontSize:
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2383
|
+
fontSize: "14px",
|
|
2384
|
+
lineHeight: "22px",
|
|
2385
|
+
color: t.labelPrimary,
|
|
2386
|
+
cursor: "pointer",
|
|
2387
|
+
whiteSpace: "nowrap"
|
|
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
|
+
}
|
|
2248
2405
|
function QrImage({ url, size = 104 }) {
|
|
2249
2406
|
const [dataUrl, setDataUrl] = (0, import_react.useState)(null);
|
|
2250
2407
|
(0, import_react.useEffect)(() => {
|
|
@@ -2270,34 +2427,24 @@ function QrImage({ url, size = 104 }) {
|
|
|
2270
2427
|
alignItems: "center",
|
|
2271
2428
|
justifyContent: "center",
|
|
2272
2429
|
lineHeight: 0,
|
|
2273
|
-
flex: "none"
|
|
2274
|
-
alignSelf: "flex-start"
|
|
2430
|
+
flex: "none"
|
|
2275
2431
|
}
|
|
2276
2432
|
},
|
|
2277
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" } })
|
|
2278
2434
|
);
|
|
2279
2435
|
}
|
|
2280
|
-
function
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel login"),
|
|
2289
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel create dsh-maestro-webhook"),
|
|
2290
|
-
(0, import_react.createElement)("li", null, "cloudflared tunnel route dns dsh-maestro-webhook <your-hostname>"),
|
|
2291
|
-
(0, import_react.createElement)("li", null, "Paste the printed Tunnel ID, the credentials file path (~/.cloudflared/<id>.json), and the hostname below.")
|
|
2292
|
-
)
|
|
2293
|
-
);
|
|
2294
|
-
}
|
|
2295
|
-
function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onChange, label }) {
|
|
2436
|
+
function ReviewModelSelector({
|
|
2437
|
+
value,
|
|
2438
|
+
catalog,
|
|
2439
|
+
fallbackValue,
|
|
2440
|
+
fallbackLabel,
|
|
2441
|
+
onChange,
|
|
2442
|
+
label
|
|
2443
|
+
}) {
|
|
2296
2444
|
const groups = catalog?.groups ?? [];
|
|
2297
2445
|
const providers = groups.map((g) => g.provider);
|
|
2298
2446
|
const selectedProvider = value?.provider ?? "";
|
|
2299
2447
|
const providerGroup = groups.find((g) => g.provider === selectedProvider);
|
|
2300
|
-
const models = providerGroup?.models ?? [];
|
|
2301
2448
|
const selectedEffort = value?.reasoningEffort ?? "";
|
|
2302
2449
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
2303
2450
|
const [pane, setPane] = (0, import_react.useState)("root");
|
|
@@ -2345,7 +2492,7 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2345
2492
|
if (filtered.length > 0) return filtered;
|
|
2346
2493
|
return ["low", "medium", "high"];
|
|
2347
2494
|
})();
|
|
2348
|
-
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;
|
|
2349
2496
|
const update = (field, newVal) => {
|
|
2350
2497
|
if (newVal === "" && field === "provider") {
|
|
2351
2498
|
onChange(null);
|
|
@@ -2359,51 +2506,30 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2359
2506
|
const first = g?.models[0];
|
|
2360
2507
|
next.provider = newVal;
|
|
2361
2508
|
next.model = first !== void 0 ? getModelId(first) : "";
|
|
2362
|
-
} else if (field === "model")
|
|
2363
|
-
|
|
2364
|
-
} else if (field === "reasoningEffort") {
|
|
2509
|
+
} else if (field === "model") next.model = newVal;
|
|
2510
|
+
else if (field === "reasoningEffort") {
|
|
2365
2511
|
if (newVal === "") delete next.reasoningEffort;
|
|
2366
2512
|
else next.reasoningEffort = newVal;
|
|
2367
2513
|
}
|
|
2368
|
-
if (!next.provider || !next.model)
|
|
2369
|
-
|
|
2370
|
-
} else {
|
|
2371
|
-
onChange(next);
|
|
2372
|
-
}
|
|
2514
|
+
if (!next.provider || !next.model) onChange(null);
|
|
2515
|
+
else onChange(next);
|
|
2373
2516
|
};
|
|
2374
2517
|
const effectiveFallback = fallbackValue !== void 0 ? fallbackValue : catalog?.current ?? null;
|
|
2375
|
-
const
|
|
2376
|
-
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;
|
|
2377
|
-
const triggerStyle = {
|
|
2378
|
-
height: 32,
|
|
2379
|
-
padding: "0 12px 0 14px",
|
|
2380
|
-
borderRadius: 20,
|
|
2381
|
-
border: "1px solid var(--dsw-alias-border-l2)",
|
|
2382
|
-
background: "var(--dsw-alias-bg-layer-2)",
|
|
2383
|
-
color: "var(--dsw-alias-label-primary)",
|
|
2384
|
-
font: "inherit",
|
|
2385
|
-
fontSize: 13,
|
|
2386
|
-
display: "inline-flex",
|
|
2387
|
-
alignItems: "center",
|
|
2388
|
-
gap: 8,
|
|
2389
|
-
cursor: "pointer",
|
|
2390
|
-
maxWidth: 320,
|
|
2391
|
-
whiteSpace: "nowrap"
|
|
2392
|
-
};
|
|
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;
|
|
2393
2519
|
const menuStyle = {
|
|
2394
2520
|
position: "absolute",
|
|
2395
2521
|
top: "calc(100% + 8px)",
|
|
2396
|
-
left: 0,
|
|
2397
|
-
minWidth:
|
|
2398
|
-
maxWidth:
|
|
2399
|
-
background:
|
|
2400
|
-
border:
|
|
2401
|
-
borderRadius:
|
|
2402
|
-
boxShadow:
|
|
2403
|
-
zIndex: 20,
|
|
2404
|
-
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"
|
|
2405
2531
|
};
|
|
2406
|
-
const
|
|
2532
|
+
const rowStyle2 = {
|
|
2407
2533
|
width: "100%",
|
|
2408
2534
|
display: "flex",
|
|
2409
2535
|
alignItems: "center",
|
|
@@ -2413,66 +2539,87 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2413
2539
|
borderRadius: 8,
|
|
2414
2540
|
border: "none",
|
|
2415
2541
|
background: "transparent",
|
|
2416
|
-
color:
|
|
2417
|
-
|
|
2542
|
+
color: t.labelPrimary,
|
|
2543
|
+
fontFamily: "inherit",
|
|
2418
2544
|
fontSize: 13,
|
|
2419
2545
|
cursor: "pointer",
|
|
2420
2546
|
textAlign: "left"
|
|
2421
2547
|
};
|
|
2422
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" } });
|
|
2423
|
-
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" }));
|
|
2424
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" }));
|
|
2425
2550
|
const effortLabel = selectedEffort === "" ? "Default effort" : selectedEffort;
|
|
2426
2551
|
const modelLabel = selectedProvider === "" ? "Select model" : value?.model ?? "Select model";
|
|
2427
2552
|
return (0, import_react.createElement)(
|
|
2428
2553
|
"div",
|
|
2429
|
-
{ ref: rootRef, style: { position: "relative", display: "inline-block", maxWidth: "100%" } },
|
|
2430
|
-
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,
|
|
2431
2556
|
(0, import_react.createElement)(
|
|
2432
2557
|
"button",
|
|
2433
|
-
{
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
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
|
+
},
|
|
2437
2584
|
(0, import_react.createElement)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, triggerLabel),
|
|
2438
|
-
|
|
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" }))
|
|
2439
2586
|
),
|
|
2440
|
-
open
|
|
2587
|
+
open ? (0, import_react.createElement)(
|
|
2441
2588
|
"div",
|
|
2442
|
-
{ style: menuStyle, role: "menu" },
|
|
2443
|
-
pane === "root"
|
|
2589
|
+
{ "data-maestro-menu": "", style: menuStyle, role: "menu" },
|
|
2590
|
+
pane === "root" ? (0, import_react.createElement)(
|
|
2444
2591
|
"div",
|
|
2445
2592
|
null,
|
|
2446
2593
|
(0, import_react.createElement)(
|
|
2447
2594
|
"button",
|
|
2448
|
-
{ type: "button", style: { ...
|
|
2595
|
+
{ type: "button", style: { ...rowStyle2, background: !value ? t.bgLayer1 : "transparent" }, onClick: () => {
|
|
2449
2596
|
onChange(null);
|
|
2450
2597
|
setOpen(false);
|
|
2451
2598
|
} },
|
|
2452
|
-
(0, import_react.createElement)("span", null,
|
|
2599
|
+
(0, import_react.createElement)("span", null, fallbackLabel),
|
|
2453
2600
|
check(!value)
|
|
2454
2601
|
),
|
|
2455
|
-
(0, import_react.createElement)("div", { style: { height: 1, background:
|
|
2602
|
+
(0, import_react.createElement)("div", { style: { height: 1, background: t.borderL2, margin: "6px 2px" } }),
|
|
2456
2603
|
(0, import_react.createElement)(
|
|
2457
2604
|
"button",
|
|
2458
|
-
{ type: "button", style:
|
|
2605
|
+
{ type: "button", style: rowStyle2, onClick: () => setPane("model") },
|
|
2459
2606
|
(0, import_react.createElement)("span", null, "Model"),
|
|
2460
|
-
(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)
|
|
2461
2608
|
),
|
|
2462
2609
|
(0, import_react.createElement)(
|
|
2463
2610
|
"button",
|
|
2464
|
-
{ type: "button", style:
|
|
2611
|
+
{ type: "button", style: rowStyle2, onClick: () => setPane("effort") },
|
|
2465
2612
|
(0, import_react.createElement)("span", null, "Effort"),
|
|
2466
|
-
(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)
|
|
2467
2614
|
),
|
|
2468
|
-
value
|
|
2469
|
-
!value && effectiveFallback
|
|
2470
|
-
warning
|
|
2471
|
-
),
|
|
2472
|
-
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)(
|
|
2473
2620
|
"div",
|
|
2474
2621
|
null,
|
|
2475
|
-
(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")),
|
|
2476
2623
|
(0, import_react.createElement)(
|
|
2477
2624
|
"div",
|
|
2478
2625
|
{ style: { maxHeight: 260, overflowY: "auto", marginTop: 4 } },
|
|
@@ -2482,33 +2629,43 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2482
2629
|
return (0, import_react.createElement)(
|
|
2483
2630
|
"div",
|
|
2484
2631
|
{ key: p, style: { marginBottom: 8 } },
|
|
2485
|
-
(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),
|
|
2486
2633
|
ms.length === 0 ? (0, import_react.createElement)("p", { style: { ...captionStyle, padding: "2px 10px 2px 28px" } }, "No models") : (0, import_react.createElement)(
|
|
2487
2634
|
"div",
|
|
2488
|
-
{ style: { marginLeft: 12, borderLeft:
|
|
2635
|
+
{ style: { marginLeft: 12, borderLeft: `1px solid ${t.borderL2}`, paddingLeft: 6, display: "flex", flexDirection: "column", gap: 2 } },
|
|
2489
2636
|
ms.map((m) => {
|
|
2490
2637
|
const mid = getModelId(m);
|
|
2491
2638
|
const mname = getModelName(m);
|
|
2492
2639
|
const active = value?.provider === p && value?.model === mid;
|
|
2493
|
-
return (0, import_react.createElement)(
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
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
|
+
);
|
|
2502
2659
|
})
|
|
2503
2660
|
)
|
|
2504
2661
|
);
|
|
2505
2662
|
})
|
|
2506
2663
|
)
|
|
2507
|
-
),
|
|
2508
|
-
pane === "effort"
|
|
2664
|
+
) : null,
|
|
2665
|
+
pane === "effort" ? (0, import_react.createElement)(
|
|
2509
2666
|
"div",
|
|
2510
2667
|
null,
|
|
2511
|
-
(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")),
|
|
2512
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)(
|
|
2513
2670
|
"div",
|
|
2514
2671
|
null,
|
|
@@ -2516,107 +2673,227 @@ function ReviewModelSelector({ value, catalog, fallbackValue, fallbackLabel, onC
|
|
|
2516
2673
|
(0, import_react.createElement)(
|
|
2517
2674
|
"div",
|
|
2518
2675
|
{ style: { marginTop: 4 } },
|
|
2519
|
-
[{ id: "", label: "Default effort" }].map(
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
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
|
+
)
|
|
2523
2687
|
),
|
|
2524
|
-
warning
|
|
2688
|
+
warning ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px", color: t.stateError } }, warning) : null
|
|
2525
2689
|
) : (0, import_react.createElement)(
|
|
2526
2690
|
"div",
|
|
2527
2691
|
null,
|
|
2528
2692
|
(0, import_react.createElement)(
|
|
2529
2693
|
"div",
|
|
2530
2694
|
{ style: { marginTop: 4 } },
|
|
2531
|
-
[{ id: "", label: "Default effort" }, ...availableEfforts.map((id) => ({ id, label: id }))].map(
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
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
|
+
)
|
|
2535
2706
|
),
|
|
2536
|
-
warning
|
|
2707
|
+
warning ? (0, import_react.createElement)("p", { style: { ...captionStyle, margin: "8px 4px 2px", color: t.stateError } }, warning) : null
|
|
2537
2708
|
)
|
|
2538
|
-
)
|
|
2539
|
-
)
|
|
2709
|
+
) : null
|
|
2710
|
+
) : null
|
|
2540
2711
|
);
|
|
2541
2712
|
}
|
|
2542
2713
|
function ProjectMappingsEditor({ mappings, onChange, catalog, globalReviewModel }) {
|
|
2543
|
-
const rows = mappings
|
|
2714
|
+
const rows = mappings;
|
|
2544
2715
|
const updateRow = (index, field, value) => {
|
|
2545
2716
|
const next = rows.map((row, i) => i === index ? { ...row, [field]: value } : row);
|
|
2546
|
-
onChange(next.filter((r) => r.projectPath !== "" || r.localRepoPath !== ""));
|
|
2717
|
+
onChange(next.filter((r) => (r.projectPath ?? "") !== "" || (r.localRepoPath ?? "") !== ""));
|
|
2547
2718
|
};
|
|
2548
2719
|
const removeRow = (index) => onChange(rows.filter((_, i) => i !== index));
|
|
2549
2720
|
const addRow = () => onChange([...rows, { projectPath: "", localRepoPath: "", reviewProfile: "magento2" }]);
|
|
2550
2721
|
return (0, import_react.createElement)(
|
|
2551
2722
|
"div",
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2723
|
+
{ "data-maestro-projects": "", style: { display: "flex", flexDirection: "column", gap: 12, paddingTop: 8 } },
|
|
2724
|
+
// Header — count + primary Add
|
|
2725
|
+
(0, import_react.createElement)(
|
|
2555
2726
|
"div",
|
|
2556
|
-
{
|
|
2557
|
-
(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) }),
|
|
2558
|
-
(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) }),
|
|
2559
|
-
(0, import_react.createElement)(
|
|
2560
|
-
"select",
|
|
2561
|
-
{ style: { ...inputStyle, flex: "0 0 130px" }, value: row.reviewProfile ?? "magento2", onChange: (e) => updateRow(i, "reviewProfile", e.target.value) },
|
|
2562
|
-
(0, import_react.createElement)("option", { value: "magento2" }, "Magento 2"),
|
|
2563
|
-
(0, import_react.createElement)("option", { value: "generic" }, "Generic")
|
|
2564
|
-
),
|
|
2727
|
+
{ style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12, padding: "4px 0 4px" } },
|
|
2565
2728
|
(0, import_react.createElement)(
|
|
2566
2729
|
"div",
|
|
2567
|
-
{ style: { flex:
|
|
2568
|
-
(0, import_react.createElement)(
|
|
2569
|
-
|
|
2570
|
-
catalog,
|
|
2571
|
-
fallbackValue: globalReviewModel ?? catalog?.current ?? null,
|
|
2572
|
-
fallbackLabel: globalReviewModel ? "Use Global" : "Use DSH default",
|
|
2573
|
-
onChange: (v) => updateRow(i, "reviewModel", v),
|
|
2574
|
-
label: null
|
|
2575
|
-
})
|
|
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")
|
|
2576
2733
|
),
|
|
2577
|
-
(0, import_react.createElement)(
|
|
2578
|
-
)
|
|
2579
|
-
(0, import_react.createElement)(
|
|
2580
|
-
);
|
|
2581
|
-
}
|
|
2582
|
-
function SecretInput({ label, placeholder, hasSaved, onSave }) {
|
|
2583
|
-
const [draft, setDraft] = (0, import_react.useState)("");
|
|
2584
|
-
const clear = () => {
|
|
2585
|
-
setDraft("");
|
|
2586
|
-
onSave("");
|
|
2587
|
-
};
|
|
2588
|
-
return (0, import_react.createElement)(
|
|
2589
|
-
"div",
|
|
2590
|
-
null,
|
|
2591
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, label),
|
|
2592
|
-
(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)(
|
|
2593
2737
|
"div",
|
|
2594
|
-
{
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
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"
|
|
2604
2750
|
}
|
|
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
|
+
)
|
|
2896
|
+
)
|
|
2620
2897
|
)
|
|
2621
2898
|
);
|
|
2622
2899
|
}
|
|
@@ -2625,40 +2902,26 @@ function LanAccess({ proxyStatus, lanPin }) {
|
|
|
2625
2902
|
const [selected, setSelected] = (0, import_react.useState)(0);
|
|
2626
2903
|
const index = Math.min(selected, Math.max(urls.length - 1, 0));
|
|
2627
2904
|
if (!proxyStatus?.running) {
|
|
2628
|
-
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");
|
|
2629
2906
|
}
|
|
2630
2907
|
return (0, import_react.createElement)(
|
|
2631
2908
|
"div",
|
|
2632
2909
|
null,
|
|
2633
|
-
(0, import_react.createElement)("p", { style: captionStyle }, lanPin?.enabled === true ? "Open this
|
|
2634
|
-
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)(
|
|
2635
2912
|
"div",
|
|
2636
2913
|
{ style: { display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 } },
|
|
2637
|
-
urls.map(
|
|
2638
|
-
key: url,
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
height: 26,
|
|
2643
|
-
padding: "0 10px",
|
|
2644
|
-
fontSize: 12,
|
|
2645
|
-
borderRadius: 13,
|
|
2646
|
-
...i === index ? { background: "var(--dsw-alias-button-primary-fill)", borderColor: "transparent", color: "var(--dsw-alias-label-primary-foreground)" } : {}
|
|
2647
|
-
}
|
|
2648
|
-
}, url.replace(/^http:\/\//, "")))
|
|
2649
|
-
),
|
|
2650
|
-
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)(
|
|
2651
2919
|
"div",
|
|
2652
|
-
{ style: { display: "flex", gap: 14, alignItems: "center" } },
|
|
2920
|
+
{ "data-maestro-qr-row": "", style: { display: "flex", gap: 14, alignItems: "center", flexWrap: "wrap" } },
|
|
2653
2921
|
(0, import_react.createElement)(QrImage, { url: urls[index], size: 116 }),
|
|
2654
|
-
(0, import_react.createElement)(
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
(0, import_react.createElement)("div", { style: codeStyle }, urls[index]),
|
|
2658
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Scan with a phone connected to the same network.")
|
|
2659
|
-
)
|
|
2660
|
-
),
|
|
2661
|
-
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
|
|
2662
2925
|
);
|
|
2663
2926
|
}
|
|
2664
2927
|
function LanPinRow({ lanPin }) {
|
|
@@ -2668,22 +2931,17 @@ function LanPinRow({ lanPin }) {
|
|
|
2668
2931
|
(0, import_react.createElement)(
|
|
2669
2932
|
"label",
|
|
2670
2933
|
{ style: { display: "flex", gap: 8, alignItems: "center", cursor: "pointer" } },
|
|
2671
|
-
(0, import_react.createElement)("input", {
|
|
2672
|
-
type: "checkbox",
|
|
2673
|
-
checked: lanPin.enabled,
|
|
2674
|
-
onChange: (e) => lanPin.onToggle(e.target.checked),
|
|
2675
|
-
style: { width: 15, height: 15, accentColor: "var(--dsw-alias-button-primary-fill)" }
|
|
2676
|
-
}),
|
|
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 } }),
|
|
2677
2935
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "Require a PIN on the LAN")
|
|
2678
2936
|
),
|
|
2679
|
-
lanPin.enabled
|
|
2937
|
+
lanPin.enabled ? (0, import_react.createElement)(
|
|
2680
2938
|
"div",
|
|
2681
|
-
{ style: { display: "flex", gap: 8, alignItems: "center", marginTop: 8 } },
|
|
2939
|
+
{ style: { display: "flex", gap: 8, alignItems: "center", marginTop: 8, flexWrap: "wrap" } },
|
|
2682
2940
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "LAN PIN"),
|
|
2683
|
-
(0, import_react.createElement)("code", { style: {
|
|
2684
|
-
lanPin.show ? (0, import_react.createElement)("
|
|
2685
|
-
(0, import_react.createElement)("
|
|
2686
|
-
)
|
|
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
|
|
2687
2945
|
);
|
|
2688
2946
|
}
|
|
2689
2947
|
function PublicAccess({ status, pin, showPin, onRevealPin, onHidePin, onRotatePin }) {
|
|
@@ -2695,27 +2953,30 @@ function PublicAccess({ status, pin, showPin, onRevealPin, onHidePin, onRotatePi
|
|
|
2695
2953
|
null,
|
|
2696
2954
|
(0, import_react.createElement)(
|
|
2697
2955
|
"div",
|
|
2698
|
-
{ 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" } },
|
|
2699
2957
|
(0, import_react.createElement)(QrImage, { url: status.publicUrl, size: 116 }),
|
|
2700
|
-
(0, import_react.createElement)(
|
|
2701
|
-
"div",
|
|
2702
|
-
null,
|
|
2703
|
-
(0, import_react.createElement)("div", { style: codeStyle }, status.publicUrl),
|
|
2704
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Works from anywhere; visitors enter the PIN below.")
|
|
2705
|
-
)
|
|
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."))
|
|
2706
2959
|
)
|
|
2707
2960
|
) : (0, import_react.createElement)("p", { style: captionStyle }, "Start the tunnel to get a public address."),
|
|
2708
2961
|
(0, import_react.createElement)(
|
|
2709
2962
|
"div",
|
|
2710
|
-
{ style: { display: "flex", gap: 8, alignItems: "center" } },
|
|
2963
|
+
{ style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" } },
|
|
2711
2964
|
(0, import_react.createElement)("span", { style: { ...fieldLabelStyle, margin: 0 } }, "Access PIN"),
|
|
2712
|
-
(0, import_react.createElement)("code", { style: {
|
|
2713
|
-
showPin ? (0, import_react.createElement)(
|
|
2714
|
-
(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")
|
|
2715
2968
|
),
|
|
2716
2969
|
(0, import_react.createElement)("p", { style: captionStyle }, "Stays the same across tunnel and DSH restarts; use Rotate when you need a new PIN.")
|
|
2717
2970
|
);
|
|
2718
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
|
+
}
|
|
2719
2980
|
function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
2720
2981
|
const [status, setStatus] = (0, import_react.useState)(null);
|
|
2721
2982
|
const [proxyStatus, setProxyStatus] = (0, import_react.useState)(null);
|
|
@@ -2728,12 +2989,58 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2728
2989
|
const [lanPinEnabled, setLanPinEnabled] = (0, import_react.useState)(false);
|
|
2729
2990
|
const [lanPin, setLanPin] = (0, import_react.useState)(null);
|
|
2730
2991
|
const [showLanPin, setShowLanPin] = (0, import_react.useState)(false);
|
|
2731
|
-
const [activeTab, setActiveTab] = (0, import_react.useState)("guard");
|
|
2732
2992
|
const [guard, setGuard] = (0, import_react.useState)({});
|
|
2733
2993
|
const [patternsText, setPatternsText] = (0, import_react.useState)("");
|
|
2734
2994
|
const [placeholdersText, setPlaceholdersText] = (0, import_react.useState)("");
|
|
2735
2995
|
const [supervisorCfg, setSupervisorCfg] = (0, import_react.useState)({});
|
|
2736
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
|
+
}, []);
|
|
2737
3044
|
const call = async (endpoint, payload) => {
|
|
2738
3045
|
const res = await rpcCall(endpoint, payload);
|
|
2739
3046
|
if (!res?.ok) throw new Error(res?.error?.message ?? "RPC failed");
|
|
@@ -2832,17 +3139,10 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2832
3139
|
});
|
|
2833
3140
|
if (configRpcCall) {
|
|
2834
3141
|
configRpcCall("get", { domain: "supervisor" }).then((res) => {
|
|
2835
|
-
if (res?.ok && res.value?.model) {
|
|
2836
|
-
setConfig((prev) => ({ ...prev, supervisorModel: res.value.model }));
|
|
2837
|
-
}
|
|
3142
|
+
if (res?.ok && res.value?.model) setConfig((prev) => ({ ...prev, supervisorModel: res.value.model }));
|
|
2838
3143
|
}).catch(() => {
|
|
2839
3144
|
});
|
|
2840
|
-
Promise.all([
|
|
2841
|
-
cfgGet("guard").catch(() => ({})),
|
|
2842
|
-
cfgGet("guardBlacklist").catch(() => ({ patterns: [], placeholders: {} })),
|
|
2843
|
-
cfgGet("supervisor").catch(() => ({})),
|
|
2844
|
-
cfgGet("notifier").catch(() => ({}))
|
|
2845
|
-
]).then(([g, bl, sup, not]) => {
|
|
3145
|
+
Promise.all([cfgGet("guard").catch(() => ({})), cfgGet("guardBlacklist").catch(() => ({ patterns: [], placeholders: {} })), cfgGet("supervisor").catch(() => ({})), cfgGet("notifier").catch(() => ({}))]).then(([g, bl, sup, not]) => {
|
|
2846
3146
|
setGuard(g ?? {});
|
|
2847
3147
|
const pats = Array.isArray(bl?.patterns) ? bl.patterns : [];
|
|
2848
3148
|
const ph = bl?.placeholders && typeof bl.placeholders === "object" ? bl.placeholders : {};
|
|
@@ -2863,8 +3163,8 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2863
3163
|
}, []);
|
|
2864
3164
|
(0, import_react.useEffect)(() => {
|
|
2865
3165
|
refresh();
|
|
2866
|
-
const
|
|
2867
|
-
return () => clearInterval(
|
|
3166
|
+
const t2 = setInterval(refresh, 3e3);
|
|
3167
|
+
return () => clearInterval(t2);
|
|
2868
3168
|
}, []);
|
|
2869
3169
|
const revealPin = async () => {
|
|
2870
3170
|
if (pin === null) {
|
|
@@ -2954,7 +3254,7 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2954
3254
|
try {
|
|
2955
3255
|
const res = await configRpcCall("set", { domain: "supervisor", patch: { model: value } });
|
|
2956
3256
|
if (res?.ok) return;
|
|
2957
|
-
} catch
|
|
3257
|
+
} catch {
|
|
2958
3258
|
}
|
|
2959
3259
|
}
|
|
2960
3260
|
try {
|
|
@@ -2963,292 +3263,131 @@ function MaestroSettingsTab({ rpcCall, configRpcCall }) {
|
|
|
2963
3263
|
setError(err.message);
|
|
2964
3264
|
}
|
|
2965
3265
|
};
|
|
2966
|
-
|
|
2967
|
-
"
|
|
2968
|
-
{
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
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)(
|
|
2979
3278
|
"div",
|
|
2980
|
-
|
|
2981
|
-
(0, import_react.createElement)("
|
|
2982
|
-
|
|
2983
|
-
(0, import_react.createElement)(
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
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 }))
|
|
2987
3292
|
),
|
|
2988
|
-
(0, import_react.createElement)(
|
|
3293
|
+
notify: (0, import_react.createElement)(
|
|
2989
3294
|
"div",
|
|
2990
|
-
{ style: {
|
|
2991
|
-
|
|
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) })
|
|
2992
3300
|
),
|
|
2993
|
-
(0, import_react.createElement)(
|
|
3301
|
+
gitlab: (0, import_react.createElement)(
|
|
2994
3302
|
"div",
|
|
2995
|
-
{ style:
|
|
2996
|
-
(0, import_react.createElement)("
|
|
2997
|
-
(0, import_react.createElement)(
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
onToggle: toggleLanPin
|
|
3007
|
-
}
|
|
3008
|
-
})
|
|
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
|
+
)
|
|
3009
3314
|
),
|
|
3010
|
-
(0, import_react.createElement)(
|
|
3315
|
+
review: (0, import_react.createElement)(
|
|
3011
3316
|
"div",
|
|
3012
|
-
{ style:
|
|
3013
|
-
(0, import_react.createElement)(
|
|
3014
|
-
(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 })
|
|
3015
3322
|
),
|
|
3016
|
-
(0, import_react.createElement)(
|
|
3323
|
+
guard: (0, import_react.createElement)(
|
|
3017
3324
|
"div",
|
|
3018
|
-
{ style:
|
|
3019
|
-
(0, import_react.createElement)(
|
|
3020
|
-
(0, import_react.createElement)(
|
|
3021
|
-
(0, import_react.createElement)(
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
hasSaved: config.hasTelegramBotToken,
|
|
3025
|
-
onSave: (value) => saveField("telegramBotToken", value)
|
|
3026
|
-
}),
|
|
3027
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "Chat ID"),
|
|
3028
|
-
(0, import_react.createElement)("input", { placeholder: "-1001234567890", autoComplete: "off", style: inputStyle, value: config.telegramChatId ?? "", onChange: (e) => saveField("telegramChatId", e.target.value) }),
|
|
3029
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3030
|
-
label: "Also notify about finished reviews",
|
|
3031
|
-
caption: "One message per review run with its outcome and a short summary.",
|
|
3032
|
-
checked: config.telegramReviewNotifications,
|
|
3033
|
-
onChange: (checked) => saveField("telegramReviewNotifications", checked)
|
|
3034
|
-
}),
|
|
3035
|
-
(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 } }) })
|
|
3036
3331
|
),
|
|
3037
|
-
(0, import_react.createElement)(
|
|
3332
|
+
blacklist: (0, import_react.createElement)(
|
|
3038
3333
|
"div",
|
|
3039
|
-
{ style:
|
|
3040
|
-
(0, import_react.createElement)(
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
placeholder: "
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "In GitLab: Settings \u2192 Webhooks, set Secret token to this value and enable Merge request events."),
|
|
3059
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Webhook URL:"),
|
|
3060
|
-
(0, import_react.createElement)("code", { style: codeStyle }, gitlabWebhookUrl(config.tunnelHostname)),
|
|
3061
|
-
(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
|
+
)
|
|
3062
3353
|
),
|
|
3063
|
-
(0, import_react.createElement)(
|
|
3354
|
+
supervisor: (0, import_react.createElement)(
|
|
3064
3355
|
"div",
|
|
3065
|
-
{ style:
|
|
3066
|
-
(0, import_react.createElement)("
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
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 }) })
|
|
3073
3366
|
),
|
|
3074
|
-
(0, import_react.createElement)(
|
|
3367
|
+
notifier: (0, import_react.createElement)(
|
|
3075
3368
|
"div",
|
|
3076
|
-
{ style:
|
|
3077
|
-
(0, import_react.createElement)("
|
|
3078
|
-
(0, import_react.createElement)(
|
|
3079
|
-
(0, import_react.createElement)(
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
label: "Global review model"
|
|
3086
|
-
})
|
|
3087
|
-
),
|
|
3088
|
-
(0, import_react.createElement)(
|
|
3089
|
-
"div",
|
|
3090
|
-
{ style: sectionStyle },
|
|
3091
|
-
(0, import_react.createElement)("h4", { style: headingStyle }, "Supervisor LLM"),
|
|
3092
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Model used by the supervisor debug-agent to auto-fix DSH Web crashes. Empty = DSH default (or Review model if set). Uses the same provider catalog as Review."),
|
|
3093
|
-
(0, import_react.createElement)(ReviewModelSelector, {
|
|
3094
|
-
value: config.supervisorModel ?? null,
|
|
3095
|
-
catalog,
|
|
3096
|
-
fallbackValue: catalog?.current ?? null,
|
|
3097
|
-
fallbackLabel: "Use DSH default",
|
|
3098
|
-
onChange: (v) => saveField("supervisorModel", v),
|
|
3099
|
-
label: "Supervisor model"
|
|
3100
|
-
})
|
|
3101
|
-
),
|
|
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" } },
|
|
3102
3378
|
(0, import_react.createElement)(
|
|
3103
3379
|
"div",
|
|
3104
|
-
{ style:
|
|
3105
|
-
(0, import_react.createElement)("
|
|
3106
|
-
(0, import_react.createElement)(
|
|
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.")
|
|
3107
3383
|
),
|
|
3108
|
-
// Task 3: Guard/Blacklist/Supervisor/Notifier tabs — data-driven over guard domains
|
|
3109
3384
|
(0, import_react.createElement)(
|
|
3110
3385
|
"div",
|
|
3111
|
-
{
|
|
3112
|
-
(0, import_react.createElement)("
|
|
3113
|
-
(0, import_react.createElement)(
|
|
3114
|
-
"div",
|
|
3115
|
-
{ style: tabBarStyle },
|
|
3116
|
-
(0, import_react.createElement)("button", { type: "button", style: tabButtonStyle(activeTab === "guard"), onClick: () => setActiveTab("guard") }, "Guard"),
|
|
3117
|
-
(0, import_react.createElement)("button", { type: "button", style: tabButtonStyle(activeTab === "blacklist"), onClick: () => setActiveTab("blacklist") }, "Blacklist"),
|
|
3118
|
-
(0, import_react.createElement)("button", { type: "button", style: tabButtonStyle(activeTab === "supervisor"), onClick: () => setActiveTab("supervisor") }, "Supervisor"),
|
|
3119
|
-
(0, import_react.createElement)("button", { type: "button", style: tabButtonStyle(activeTab === "notifier"), onClick: () => setActiveTab("notifier") }, "Notifier")
|
|
3120
|
-
),
|
|
3121
|
-
activeTab === "guard" && (0, import_react.createElement)(
|
|
3122
|
-
"div",
|
|
3123
|
-
{ "data-tab": "guard" },
|
|
3124
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Enforce publish block, git protection and cwd containment."),
|
|
3125
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3126
|
-
label: "publishBlocked",
|
|
3127
|
-
caption: "Block publish-related commands when enabled.",
|
|
3128
|
-
checked: guard.publishBlocked === true,
|
|
3129
|
-
onChange: (v) => saveGuard({ publishBlocked: v })
|
|
3130
|
-
}),
|
|
3131
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3132
|
-
label: "gitProtection.enabled",
|
|
3133
|
-
caption: "Protect pushes to protected branches.",
|
|
3134
|
-
checked: guard.gitProtection?.enabled === true,
|
|
3135
|
-
onChange: (v) => saveGuard({ gitProtection: { enabled: v, branches: guard.gitProtection?.branches ?? ["master", "main"] } })
|
|
3136
|
-
}),
|
|
3137
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "gitProtection.branches (comma separated)"),
|
|
3138
|
-
(0, import_react.createElement)("input", {
|
|
3139
|
-
style: inputStyle,
|
|
3140
|
-
value: (guard.gitProtection?.branches ?? ["master", "main"]).join(", "),
|
|
3141
|
-
placeholder: "master, main",
|
|
3142
|
-
onChange: (e) => {
|
|
3143
|
-
const branches = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
3144
|
-
saveGuard({ gitProtection: { enabled: guard.gitProtection?.enabled ?? true, branches } });
|
|
3145
|
-
}
|
|
3146
|
-
}),
|
|
3147
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3148
|
-
label: "cwdContainment",
|
|
3149
|
-
caption: "Contain file operations to the session cwd.",
|
|
3150
|
-
checked: guard.cwdContainment === true,
|
|
3151
|
-
onChange: (v) => saveGuard({ cwdContainment: v })
|
|
3152
|
-
}),
|
|
3153
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "credentialPaths (comma separated)"),
|
|
3154
|
-
(0, import_react.createElement)("input", {
|
|
3155
|
-
style: inputStyle,
|
|
3156
|
-
value: (guard.credentialPaths ?? []).join(", "),
|
|
3157
|
-
placeholder: "~/.config/credentials.yaml, ~/.config/cloudflared",
|
|
3158
|
-
onChange: (e) => {
|
|
3159
|
-
const credentialPaths = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
3160
|
-
saveGuard({ credentialPaths });
|
|
3161
|
-
}
|
|
3162
|
-
})
|
|
3163
|
-
),
|
|
3164
|
-
activeTab === "blacklist" && (0, import_react.createElement)(
|
|
3165
|
-
"div",
|
|
3166
|
-
{ "data-tab": "blacklist" },
|
|
3167
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "One pattern per line. These are blocked from being committed or published."),
|
|
3168
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "patterns (one per line)"),
|
|
3169
|
-
(0, import_react.createElement)("textarea", {
|
|
3170
|
-
style: textareaStyle,
|
|
3171
|
-
value: patternsText,
|
|
3172
|
-
placeholder: "example-project\nacme-shop",
|
|
3173
|
-
onChange: (e) => setPatternsText(e.target.value),
|
|
3174
|
-
onBlur: (e) => commitBlacklistPatterns(e.target.value)
|
|
3175
|
-
}),
|
|
3176
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "placeholders JSON"),
|
|
3177
|
-
(0, import_react.createElement)("textarea", {
|
|
3178
|
-
style: { ...textareaStyle, height: 90 },
|
|
3179
|
-
value: placeholdersText,
|
|
3180
|
-
placeholder: '{"example-project":"my-project"}',
|
|
3181
|
-
onChange: (e) => setPlaceholdersText(e.target.value),
|
|
3182
|
-
onBlur: () => commitPlaceholders()
|
|
3183
|
-
}),
|
|
3184
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Map blocked patterns to their placeholder suggestions."),
|
|
3185
|
-
(0, import_react.createElement)("button", { type: "button", style: { ...secondaryButtonStyle, marginTop: 8 }, onClick: () => {
|
|
3186
|
-
commitBlacklistPatterns(patternsText);
|
|
3187
|
-
commitPlaceholders();
|
|
3188
|
-
} }, "Save Blacklist")
|
|
3189
|
-
),
|
|
3190
|
-
activeTab === "supervisor" && (0, import_react.createElement)(
|
|
3191
|
-
"div",
|
|
3192
|
-
{ "data-tab": "supervisor" },
|
|
3193
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Background daemon that auto-resumes crashed sessions."),
|
|
3194
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "intervalMs"),
|
|
3195
|
-
(0, import_react.createElement)("input", {
|
|
3196
|
-
type: "number",
|
|
3197
|
-
style: inputStyle,
|
|
3198
|
-
value: supervisorCfg.intervalMs ?? "",
|
|
3199
|
-
placeholder: "5000",
|
|
3200
|
-
onChange: (e) => {
|
|
3201
|
-
const v = e.target.value === "" ? void 0 : Number(e.target.value);
|
|
3202
|
-
saveSupervisorCfg({ intervalMs: v });
|
|
3203
|
-
}
|
|
3204
|
-
}),
|
|
3205
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "downThreshold"),
|
|
3206
|
-
(0, import_react.createElement)("input", {
|
|
3207
|
-
type: "number",
|
|
3208
|
-
style: inputStyle,
|
|
3209
|
-
value: supervisorCfg.downThreshold ?? "",
|
|
3210
|
-
placeholder: "3",
|
|
3211
|
-
onChange: (e) => {
|
|
3212
|
-
const v = e.target.value === "" ? void 0 : Number(e.target.value);
|
|
3213
|
-
saveSupervisorCfg({ downThreshold: v });
|
|
3214
|
-
}
|
|
3215
|
-
}),
|
|
3216
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3217
|
-
label: "autoResumeEnabled",
|
|
3218
|
-
caption: "Automatically resume down sessions.",
|
|
3219
|
-
checked: supervisorCfg.autoResumeEnabled === true,
|
|
3220
|
-
onChange: (v) => saveSupervisorCfg({ autoResumeEnabled: v })
|
|
3221
|
-
})
|
|
3222
|
-
),
|
|
3223
|
-
activeTab === "notifier" && (0, import_react.createElement)(
|
|
3224
|
-
"div",
|
|
3225
|
-
{ "data-tab": "notifier" },
|
|
3226
|
-
(0, import_react.createElement)("p", { style: captionStyle }, "Telegram notifications for Maestro events."),
|
|
3227
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "telegram.botToken"),
|
|
3228
|
-
(0, import_react.createElement)("input", {
|
|
3229
|
-
type: "password",
|
|
3230
|
-
autoComplete: "off",
|
|
3231
|
-
style: inputStyle,
|
|
3232
|
-
value: notifierCfg.telegram?.botToken ?? "",
|
|
3233
|
-
placeholder: "123456:ABC-DEF...",
|
|
3234
|
-
onChange: (e) => saveNotifierCfg({ telegram: { botToken: e.target.value } })
|
|
3235
|
-
}),
|
|
3236
|
-
(0, import_react.createElement)("label", { style: fieldLabelStyle }, "telegram.chatId"),
|
|
3237
|
-
(0, import_react.createElement)("input", {
|
|
3238
|
-
style: inputStyle,
|
|
3239
|
-
value: notifierCfg.telegram?.chatId ?? "",
|
|
3240
|
-
placeholder: "-1001234567890",
|
|
3241
|
-
onChange: (e) => saveNotifierCfg({ telegram: { chatId: e.target.value } })
|
|
3242
|
-
}),
|
|
3243
|
-
(0, import_react.createElement)(ToggleField, {
|
|
3244
|
-
label: "telegram.reviewNotifications",
|
|
3245
|
-
caption: "Also notify about finished reviews.",
|
|
3246
|
-
checked: notifierCfg.telegram?.reviewNotifications === true || notifierCfg.policy?.reviewNotifications === true,
|
|
3247
|
-
onChange: (v) => saveNotifierCfg({ telegram: { reviewNotifications: v } })
|
|
3248
|
-
})
|
|
3249
|
-
)
|
|
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))
|
|
3250
3388
|
),
|
|
3251
|
-
|
|
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
|
|
3252
3391
|
);
|
|
3253
3392
|
}
|
|
3254
3393
|
|
|
@@ -3289,7 +3428,7 @@ function registerSettingsNavIcon(label, root) {
|
|
|
3289
3428
|
}
|
|
3290
3429
|
|
|
3291
3430
|
// src/client/index.tsx
|
|
3292
|
-
var
|
|
3431
|
+
var SETTINGS_NAV_CSS = `
|
|
3293
3432
|
|
|
3294
3433
|
/* maestro: replace the settings-nav fallback gear with the Maestro M-logo glyph */
|
|
3295
3434
|
[${SETTINGS_NAV_MARKER}] > svg:first-child {
|
|
@@ -3311,7 +3450,7 @@ function installNavIconStyle() {
|
|
|
3311
3450
|
const tag = document.createElement("style");
|
|
3312
3451
|
tag.dataset.plugin = "@ddtcorex/dsh-maestro-config";
|
|
3313
3452
|
tag.dataset.pluginCss = "maestro/settings-nav.css";
|
|
3314
|
-
tag.textContent =
|
|
3453
|
+
tag.textContent = SETTINGS_NAV_CSS;
|
|
3315
3454
|
document.head.appendChild(tag);
|
|
3316
3455
|
return () => {
|
|
3317
3456
|
document.querySelector('style[data-plugin-css="maestro/settings-nav.css"]')?.remove();
|