@matamt-dbg/dsh-studio 0.2.2 → 0.2.8
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/README.md +9 -4
- package/client.js +499 -219
- package/index.js +340 -64
- package/package.json +1 -1
- package/policy.js +135 -12
- package/roles.js +25 -3
package/client.js
CHANGED
|
@@ -93,6 +93,8 @@ function parsePreviewRequest(value) {
|
|
|
93
93
|
if (row.providerConfigs !== void 0 && (!record2(row.providerConfigs) || Object.values(row.providerConfigs).some((v) => !record2(v)))) throw new Error("Invalid provider configs");
|
|
94
94
|
if (row.configOverrides !== void 0) validateConfigOverrides(row.configOverrides);
|
|
95
95
|
if (row.execution !== void 0) validateExecutionDefaults(row.execution);
|
|
96
|
+
const filter = row.subagentToolFilter;
|
|
97
|
+
if (filter !== void 0 && (!record2(filter) || !strings(filter.deny) || filter.deny.some((name) => !name))) throw new Error("Invalid subagent tool filter");
|
|
96
98
|
return {
|
|
97
99
|
...row.configOverrides !== void 0 ? { configOverrides: row.configOverrides } : {},
|
|
98
100
|
...row.execution !== void 0 ? { execution: row.execution } : {},
|
|
@@ -104,7 +106,8 @@ function parsePreviewRequest(value) {
|
|
|
104
106
|
...row.persona !== void 0 ? { persona: row.persona } : {},
|
|
105
107
|
...row.sections !== void 0 ? { sections: row.sections } : {},
|
|
106
108
|
...row.toolOverrides !== void 0 ? { toolOverrides: row.toolOverrides } : {},
|
|
107
|
-
...row.providerConfigs !== void 0 ? { providerConfigs: row.providerConfigs } : {}
|
|
109
|
+
...row.providerConfigs !== void 0 ? { providerConfigs: row.providerConfigs } : {},
|
|
110
|
+
...filter !== void 0 && filter.deny.length ? { subagentToolFilter: { deny: [...new Set(filter.deny)] } } : {}
|
|
108
111
|
};
|
|
109
112
|
}
|
|
110
113
|
|
|
@@ -112,8 +115,7 @@ function parsePreviewRequest(value) {
|
|
|
112
115
|
var import_react = __toESM(require("react"), 1);
|
|
113
116
|
|
|
114
117
|
// src/ui-styles.ts
|
|
115
|
-
var
|
|
116
|
-
.studio-ui {
|
|
118
|
+
var adapter = `.studio-ui {
|
|
117
119
|
--studio-bg: var(--dsw-alias-bg-base);
|
|
118
120
|
--studio-surface: var(--dsw-alias-bg-layer-1);
|
|
119
121
|
--studio-inset: var(--dsw-alias-bg-layer-2);
|
|
@@ -145,7 +147,9 @@ var studioStyles = `/* Only this adapter references host tokens. Studio never in
|
|
|
145
147
|
min-width: 0;
|
|
146
148
|
overflow-wrap: anywhere;
|
|
147
149
|
}
|
|
148
|
-
|
|
150
|
+
`;
|
|
151
|
+
var studioStyles = `/* Only this adapter references host tokens. Studio never installs a global theme. */
|
|
152
|
+
${adapter}.studio-ui *, .studio-ui *::before, .studio-ui *::after { box-sizing: border-box; }
|
|
149
153
|
.studio-ui .studio-tool-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 12px; }
|
|
150
154
|
.studio-ui .studio-tool-card { display: flex; flex-direction: column; gap: 8px; padding: 14px; border: 1px solid var(--studio-line); border-radius: var(--studio-radius); cursor: pointer; min-width: 0; }
|
|
151
155
|
.studio-ui .studio-tool-card[data-selected="true"] { background: var(--studio-hover); border-color: var(--studio-ink); }
|
|
@@ -214,6 +218,14 @@ var studioStyles = `/* Only this adapter references host tokens. Studio never in
|
|
|
214
218
|
.studio-ui .studio-service-panel[hidden] { display: none; }
|
|
215
219
|
.studio-ui .studio-service-panel > .studio-ui { max-width: 960px; margin: 0 auto; padding: 24px clamp(16px, 3vw, 40px) 48px; }
|
|
216
220
|
.studio-ui .studio-layout { display: grid; grid-template-columns: 208px minmax(0, 1fr); height: 100%; }
|
|
221
|
+
/* Version footer pinned to the bottom of the Studio navigation. */
|
|
222
|
+
.studio-ui .studio-nav-footer { display: flex; align-items: center; gap: 6px; margin-top: auto; padding: 12px 10px 0; color: var(--studio-subtle); font-size: 12px; }
|
|
223
|
+
.studio-ui .studio-icon-button { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: var(--studio-small-radius); background: none; color: var(--studio-info); cursor: pointer; }
|
|
224
|
+
.studio-ui .studio-icon-button:hover:not(:disabled) { background: var(--studio-hover); }
|
|
225
|
+
.studio-ui .studio-icon-button[data-tone=success] { color: var(--studio-success); }
|
|
226
|
+
.studio-ui .studio-icon-button[data-tone=error] { color: var(--studio-error); }
|
|
227
|
+
.studio-ui .studio-icon-button:disabled { cursor: default; opacity: 1; }
|
|
228
|
+
.studio-ui .studio-icon-button[aria-busy=true] { opacity: .5; }
|
|
217
229
|
.studio-ui nav.studio-nav { display: flex; flex-direction: column; flex-wrap: nowrap; gap: 2px; margin: 0; padding: 24px 12px; border-inline-end: .5px solid var(--studio-line); overflow-y: auto; }
|
|
218
230
|
.studio-ui .studio-nav-head { display: grid; gap: 2px; padding: 0 10px 8px; }
|
|
219
231
|
.studio-ui .studio-nav-title { font-size: 14px; }
|
|
@@ -604,6 +616,7 @@ var studioStyles = `/* Only this adapter references host tokens. Studio never in
|
|
|
604
616
|
.studio-ui nav.studio-nav { flex-direction: row; overflow-x: auto; padding: 8px 12px; border-inline-end: 0; border-bottom: .5px solid var(--studio-line); }
|
|
605
617
|
.studio-ui .studio-nav-title, .studio-ui .studio-nav-group { display: none; }
|
|
606
618
|
.studio-ui .studio-nav-item { flex: 0 0 auto; }
|
|
619
|
+
.studio-ui .studio-nav-footer { margin: 0 0 0 auto; padding: 0 0 0 8px; }
|
|
607
620
|
.studio-ui .studio-scroller { overflow: visible; }
|
|
608
621
|
}
|
|
609
622
|
@container studio-main (max-width: 560px) {
|
|
@@ -622,6 +635,13 @@ var studioStyles = `/* Only this adapter references host tokens. Studio never in
|
|
|
622
635
|
.studio-ui dd { margin-bottom: 8px; }
|
|
623
636
|
}
|
|
624
637
|
`;
|
|
638
|
+
var sidebarMarkStyles = `${adapter}
|
|
639
|
+
.studio-ui.studio-sidebar-glyph { display: inline-flex; color: inherit; line-height: 0; }
|
|
640
|
+
.studio-ui .studio-sidebar-dot { fill: var(--studio-info); }
|
|
641
|
+
/* order keeps the mark last even if the sidebar later appends its own label. */
|
|
642
|
+
.studio-ui.studio-sidebar-update { display: inline-flex; flex: none; align-items: center; order: 99; margin-left: auto; color: var(--studio-info); line-height: 0; }
|
|
643
|
+
.studio-ui.studio-sidebar-update[data-phase=failed] { color: var(--studio-error); }
|
|
644
|
+
`;
|
|
625
645
|
|
|
626
646
|
// src/ui.tsx
|
|
627
647
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -699,6 +719,9 @@ function SplitButton({ label, onClick, primary = false, disabled = false, action
|
|
|
699
719
|
}, children: action.label }, action.label)) })
|
|
700
720
|
] });
|
|
701
721
|
}
|
|
722
|
+
function IconButton({ label, tone = "info", disabled = false, busy = false, onClick, children }) {
|
|
723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "studio-icon-button", "data-tone": tone, title: label, "aria-label": label, "aria-busy": busy || void 0, disabled, onClick, children });
|
|
724
|
+
}
|
|
702
725
|
function DetailDialog({ open, title, subtitle, onClose, closeLabel, footer, wide = false, compact = false, children }) {
|
|
703
726
|
const ref = import_react.default.useRef(null);
|
|
704
727
|
const opener = import_react.default.useRef(null);
|
|
@@ -733,15 +756,76 @@ function DetailDialog({ open, title, subtitle, onClose, closeLabel, footer, wide
|
|
|
733
756
|
}
|
|
734
757
|
|
|
735
758
|
// src/role-editor.tsx
|
|
759
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
760
|
+
|
|
761
|
+
// src/item-picker.tsx
|
|
736
762
|
var import_react2 = __toESM(require("react"), 1);
|
|
737
763
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
738
|
-
function
|
|
739
|
-
const
|
|
740
|
-
const [
|
|
741
|
-
const [
|
|
742
|
-
const
|
|
743
|
-
const
|
|
744
|
-
const
|
|
764
|
+
function ItemPicker({ label, items, selected, onChange, labels, renderDetails, isModified, hasDetails }) {
|
|
765
|
+
const [query, setQuery] = import_react2.default.useState("");
|
|
766
|
+
const [filter, setFilter] = import_react2.default.useState("all");
|
|
767
|
+
const [detail, setDetail] = import_react2.default.useState();
|
|
768
|
+
const chosen = new Set(selected);
|
|
769
|
+
const isOn = (item) => item.lockedReason !== void 0 || chosen.has(item.name);
|
|
770
|
+
const modified = (name) => chosen.has(name) && (isModified?.(name) ?? false);
|
|
771
|
+
const text = query.trim().toLowerCase();
|
|
772
|
+
const visible = items.filter((item) => (filter === "all" || (filter === "selected" ? isOn(item) : modified(item.name))) && (!text || `${item.name}
|
|
773
|
+
${item.title ?? ""}
|
|
774
|
+
${item.description}
|
|
775
|
+
${item.searchText ?? ""}`.toLowerCase().includes(text)));
|
|
776
|
+
const counts = { all: items.length, selected: items.filter(isOn).length, modified: items.filter((item) => modified(item.name)).length };
|
|
777
|
+
const toggle = (name) => onChange(chosen.has(name) ? selected.filter((value) => value !== name) : [...selected, name]);
|
|
778
|
+
const open = items.find((item) => item.name === detail && chosen.has(item.name));
|
|
779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "studio-picker", children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "studio-picker-bar", children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "search", "aria-label": labels.search, placeholder: labels.searchHint, value: query, onChange: (event) => setQuery(event.target.value) }),
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "studio-picker-filters", role: "radiogroup", "aria-label": labels.filter, children: ["all", "selected", "modified"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", role: "radio", "aria-checked": filter === value, className: "studio-picker-filter", onClick: () => setFilter(value), children: [
|
|
783
|
+
labels[value],
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "studio-count", children: counts[value] })
|
|
785
|
+
] }, value)) })
|
|
786
|
+
] }),
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "studio-picker-list", "aria-label": label, children: [
|
|
788
|
+
visible.map((item) => {
|
|
789
|
+
const locked = item.lockedReason !== void 0;
|
|
790
|
+
const on = locked || chosen.has(item.name);
|
|
791
|
+
const blocked = locked || !on && item.disabledReason !== void 0;
|
|
792
|
+
const details = on && renderDetails !== void 0 && (hasDetails?.(item.name) ?? true);
|
|
793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "studio-picker-row", "data-selected": on, children: [
|
|
794
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", role: "switch", "aria-checked": on, disabled: blocked, className: "studio-picker-toggle", "aria-label": `${item.title ?? item.name}`, onClick: () => toggle(item.name), children: [
|
|
795
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "studio-picker-check", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3.5 8.5l3 3 6-7", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "studio-picker-text", children: [
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "studio-picker-title", children: [
|
|
798
|
+
item.title ?? item.name,
|
|
799
|
+
item.subtitle && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "studio-picker-subtitle studio-mono", children: item.subtitle })
|
|
800
|
+
] }),
|
|
801
|
+
(locked ? item.lockedReason : item.disabledReason && !on ? item.disabledReason : item.description) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "studio-picker-description", children: locked ? item.lockedReason : item.disabledReason && !on ? item.disabledReason : item.description })
|
|
802
|
+
] })
|
|
803
|
+
] }),
|
|
804
|
+
modified(item.name) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "studio-badge", "data-tone": "info", "data-studio-modified": "true", children: labels.modifiedTag }),
|
|
805
|
+
details && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Button, { small: true, "aria-label": `${labels.settings}: ${item.name}`, "aria-haspopup": "dialog", onClick: () => setDetail(item.name), children: labels.settings })
|
|
806
|
+
] }, item.name);
|
|
807
|
+
}),
|
|
808
|
+
!visible.length && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "studio-picker-empty", role: "status", children: [
|
|
809
|
+
text ? labels.noResults : labels.empty,
|
|
810
|
+
(text || filter !== "all") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Button, { small: true, onClick: () => {
|
|
811
|
+
setQuery("");
|
|
812
|
+
setFilter("all");
|
|
813
|
+
}, children: labels.clear })
|
|
814
|
+
] })
|
|
815
|
+
] }),
|
|
816
|
+
renderDetails && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DetailDialog, { open: open !== void 0, title: open?.title ?? open?.name, subtitle: open?.subtitle, closeLabel: labels.done, onClose: () => setDetail(void 0), children: open && renderDetails(open.name) })
|
|
817
|
+
] });
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// src/role-editor.tsx
|
|
821
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
822
|
+
function RoleEditor({ locale, roles, onChange, loadModels, defaultPersona = "", tools, hiddenTools = [], onHiddenToolsChange, delegates = true }) {
|
|
823
|
+
const t = (ko3, en3, zh3) => locale.startsWith("ko") ? ko3 : locale.startsWith("zh") ? zh3 : en3;
|
|
824
|
+
const [selected, setSelected] = import_react3.default.useState();
|
|
825
|
+
const [catalog, setCatalog] = import_react3.default.useState();
|
|
826
|
+
const [error, setError] = import_react3.default.useState("");
|
|
827
|
+
const [loading, setLoading] = import_react3.default.useState(false);
|
|
828
|
+
const refresh = import_react3.default.useCallback(async () => {
|
|
745
829
|
if (!loadModels) return;
|
|
746
830
|
setLoading(true);
|
|
747
831
|
setError("");
|
|
@@ -753,120 +837,179 @@ function RoleEditor({ locale, roles, onChange, loadModels, defaultPersona = "" }
|
|
|
753
837
|
setLoading(false);
|
|
754
838
|
}
|
|
755
839
|
}, [loadModels]);
|
|
756
|
-
|
|
840
|
+
import_react3.default.useEffect(() => {
|
|
757
841
|
void refresh();
|
|
758
842
|
}, [refresh]);
|
|
759
843
|
const models = (catalog?.groups ?? []).flatMap((group) => group.models.map((model2) => ({ ...model2, value: `${group.id}/${model2.id}`, label: `${group.name} \xB7 ${model2.name}` })));
|
|
760
844
|
const role = selected === void 0 ? void 0 : roles[selected];
|
|
761
845
|
const model = models.find((model2) => model2.value === role?.model);
|
|
762
|
-
const update2 = (patch) => onChange(roles.map((role2, index) =>
|
|
763
|
-
|
|
764
|
-
|
|
846
|
+
const update2 = (patch) => onChange(roles.map((role2, index) => {
|
|
847
|
+
if (index !== selected) return role2;
|
|
848
|
+
const next = { ...role2, ...patch };
|
|
849
|
+
if (next.toolFilter === void 0) delete next.toolFilter;
|
|
850
|
+
return next;
|
|
851
|
+
}));
|
|
852
|
+
const field2 = (label, content) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "studio-field", children: [
|
|
853
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: label }),
|
|
765
854
|
content
|
|
766
855
|
] });
|
|
767
856
|
const close = () => setSelected(void 0);
|
|
768
|
-
|
|
769
|
-
|
|
857
|
+
const defaultCount = hiddenTools.filter((name) => tools?.some((tool) => tool.name === name)).length;
|
|
858
|
+
const filterTitle = t("\uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8 Tool Filter", "Subagent Tool Filter", "\u5B50\u4EE3\u7406 Tool Filter");
|
|
859
|
+
const roleFilterLabel = t("\uC774 \uC5ED\uD560\uC758 Tool Filter", "Tool Filter for this role", "\u6B64\u89D2\u8272\u7684 Tool Filter");
|
|
860
|
+
const filterSummary = (item) => {
|
|
861
|
+
const own2 = item.toolFilter?.deny.filter((name) => tools?.some((tool) => tool.name === name) && !(item.toolFilter?.mode === "extend" && hiddenTools.includes(name))).length ?? 0;
|
|
862
|
+
return !item.toolFilter ? t("\uAE30\uBCF8\uAC12", "default", "\u9ED8\u8BA4") : item.toolFilter.mode === "extend" ? t(`\uAE30\uBCF8\uAC12 + ${own2}`, `default + ${own2}`, `\u9ED8\u8BA4 + ${own2}`) : t(`\uB530\uB85C ${own2}`, `own ${own2}`, `\u5355\u72EC ${own2}`);
|
|
863
|
+
};
|
|
864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
865
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SectionHead, { title: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("h3", { className: "studio-panel-title", children: [
|
|
770
866
|
t("\uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8", "Subagents", "\u5B50\u4EE3\u7406"),
|
|
771
|
-
/* @__PURE__ */ (0,
|
|
772
|
-
] }), description: t("\uBC14\uAFBC \uB0B4\uC6A9\uC740 \uD504\uB9AC\uC14B\uC744 \uC800\uC7A5\uD558\uACE0 DSH\uC5D0 \uB2E4\uC2DC \uBC18\uC601\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.", "Save the preset and reapply it to DSH after changes.", "\u4FEE\u6539\u540E\u9700\u4FDD\u5B58\u9884\u8BBE\u5E76\u91CD\u65B0\u5E94\u7528\u5230 DSH\u3002"), actions: /* @__PURE__ */ (0,
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
867
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "studio-count", children: roles.length })
|
|
868
|
+
] }), description: t("\uBC14\uAFBC \uB0B4\uC6A9\uC740 \uD504\uB9AC\uC14B\uC744 \uC800\uC7A5\uD558\uACE0 DSH\uC5D0 \uB2E4\uC2DC \uBC18\uC601\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.", "Save the preset and reapply it to DSH after changes.", "\u4FEE\u6539\u540E\u9700\u4FDD\u5B58\u9884\u8BBE\u5E76\u91CD\u65B0\u5E94\u7528\u5230 DSH\u3002"), actions: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
869
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { small: true, disabled: loading || !loadModels, onClick: () => void refresh(), children: loading ? t("\uBAA8\uB378 \uBD88\uB7EC\uC624\uB294 \uC911\u2026", "Loading models\u2026", "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u2026") : t("\uBAA8\uB378 \uBAA9\uB85D \uC0C8\uB85C\uACE0\uCE68", "Refresh models", "\u5237\u65B0\u6A21\u578B\u5217\u8868") }),
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { small: true, onClick: () => {
|
|
775
871
|
setSelected(roles.length);
|
|
776
872
|
onChange([...roles, { name: "", role: "", model: "inherit", reasoning: "inherit", spawn: "fresh", persona: "" }]);
|
|
777
873
|
}, children: t("\uC5ED\uD560 \uCD94\uAC00", "Add role", "\u6DFB\u52A0\u89D2\u8272") })
|
|
778
874
|
] }) }),
|
|
779
|
-
error && /* @__PURE__ */ (0,
|
|
780
|
-
catalog?.failures.map((failure) => /* @__PURE__ */ (0,
|
|
875
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Note, { children: error }),
|
|
876
|
+
catalog?.failures.map((failure) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Note, { children: [
|
|
781
877
|
failure.name,
|
|
782
878
|
": ",
|
|
783
879
|
failure.message
|
|
784
880
|
] }, failure.name)),
|
|
785
|
-
/* @__PURE__ */ (0,
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Note, { children: t(
|
|
786
882
|
"DSH\uC758 \uAE30\uBCF8 \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8 \uB3C4\uAD6C(subagent, subagent_fork, list_subagent_models)\uB97C subagent_role \uD558\uB098\uB85C \uD1B5\uD569\uD574 \uC81C\uACF5\uD569\uB2C8\uB2E4. \uAE30\uBCF8 \uB3C4\uAD6C\uB294 \uC790\uB3D9\uC73C\uB85C \uBE60\uC9C0\uACE0, subagent_role\uC758 \uC124\uBA85\uACFC \uC778\uC790\uB294 \uD504\uB86C\uD504\uD2B8\xB7\uB3C4\uAD6C \uD0ED\uC758 \uB3C4\uAD6C \uBAA9\uB85D\uC5D0\uC11C \uD655\uC778\uD558\uACE0 \uC218\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
787
|
-
"Studio
|
|
883
|
+
"Studio replaces the DSH default subagent tools (subagent, subagent_fork, list_subagent_models) with a single subagent_role tool. The default tools are removed automatically; review or edit subagent_role in the tool list on the Prompts & tools tab.",
|
|
788
884
|
"\u5C06 DSH \u9ED8\u8BA4\u5B50\u4EE3\u7406\u5DE5\u5177\uFF08subagent\u3001subagent_fork\u3001list_subagent_models\uFF09\u5408\u5E76\u4E3A\u4E00\u4E2A subagent_role \u5DE5\u5177\u63D0\u4F9B\u3002\u9ED8\u8BA4\u5DE5\u5177\u4F1A\u88AB\u81EA\u52A8\u79FB\u9664\uFF1B\u53EF\u5728\u201C\u63D0\u793A\u8BCD\u4E0E\u5DE5\u5177\u201D\u9875\u7684\u5DE5\u5177\u5217\u8868\u4E2D\u67E5\u770B\u6216\u7F16\u8F91 subagent_role\u3002"
|
|
789
885
|
) }),
|
|
790
|
-
!roles.length && /* @__PURE__ */ (0,
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
886
|
+
!roles.length && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "studio-muted", role: "status", children: t("\uC815\uC758\uB41C \uC5ED\uD560\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774 \uC0C1\uD0DC\uC5D0\uC11C\uB294 subagent_role\uC774 \uBD80\uBAA8\uC640 \uAC19\uC740 \uBAA8\uB378\xB7\uCD94\uB860\xB7\uC9C0\uCE68\uC73C\uB85C \uC0C8 \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4.", "No roles defined. subagent_role then starts a new subagent with the same model, reasoning and instructions as the parent.", "\u5C1A\u672A\u5B9A\u4E49\u89D2\u8272\u3002\u6B64\u65F6 subagent_role \u4F1A\u4EE5\u4E0E\u7236\u4EE3\u7406\u76F8\u540C\u7684\u6A21\u578B\u3001\u63A8\u7406\u548C\u6307\u4EE4\u542F\u52A8\u65B0\u7684\u5B50\u4EE3\u7406\u3002") }),
|
|
887
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "studio-tool-cards studio-card-pair", children: roles.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "studio-role-card", children: [
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "studio-card-head", children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: item.name || t("\uC774\uB984 \uC5C6\uC74C", "Untitled", "\u672A\u547D\u540D") }),
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Badge, { tone: "outline", children: item.spawn === "fork" ? t("\uBD80\uBAA8 \uB300\uD654 \uC774\uC5B4\uBC1B\uAE30", "Continue parent", "\u7EE7\u627F\u7236\u5BF9\u8BDD") : t("\uC0C8 \uB300\uD654", "New conversation", "\u65B0\u5BF9\u8BDD") })
|
|
795
891
|
] }),
|
|
796
|
-
item.role && /* @__PURE__ */ (0,
|
|
797
|
-
/* @__PURE__ */ (0,
|
|
892
|
+
item.role && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "studio-card-text studio-mono", children: item.role }),
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "studio-card-meta", children: [
|
|
798
894
|
item.model === "inherit" ? t("\uBD80\uBAA8 \uBAA8\uB378 \uC0AC\uC6A9", "Inherit parent model", "\u7EE7\u627F\u7236\u7EA7\u6A21\u578B") : models.find((model2) => model2.value === item.model)?.label ?? item.model,
|
|
799
895
|
" \xB7 ",
|
|
800
896
|
t("\uCD94\uB860", "Reasoning", "\u63A8\u7406"),
|
|
801
897
|
" ",
|
|
802
|
-
item.reasoning === "inherit" ? t("\uAE30\uBCF8", "
|
|
898
|
+
item.reasoning === "inherit" ? t("\uAE30\uBCF8\uAC12", "default", "\u9ED8\u8BA4") : item.reasoning,
|
|
899
|
+
tools && delegates && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
900
|
+
" \xB7 Tool Filter: ",
|
|
901
|
+
filterSummary(item)
|
|
902
|
+
] })
|
|
803
903
|
] }),
|
|
804
|
-
/* @__PURE__ */ (0,
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "studio-card-footer", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { small: true, "aria-haspopup": "dialog", onClick: () => setSelected(index), children: t("\uD3B8\uC9D1", "Edit", "\u7F16\u8F91") }) })
|
|
805
905
|
] }, index)) }),
|
|
806
|
-
/* @__PURE__ */ (0,
|
|
906
|
+
tools && onHiddenToolsChange && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "studio-form-section", children: [
|
|
907
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SectionHead, { title: filterTitle, description: t("Tool Filter\uC5D0 \uB4F1\uB85D\uD55C \uB3C4\uAD6C\uB294 \uC774 \uD504\uB9AC\uC14B\uC758 \uBAA8\uB4E0 \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uBE60\uC9D1\uB2C8\uB2E4. \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uC758 \uC2DC\uC2A4\uD15C \uD504\uB86C\uD504\uD2B8\uC5D0\uC11C \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C \uD544\uC694 \uC5C6\uB294 \uB3C4\uAD6C\uB97C \uC81C\uAC70\uD574 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uAC00\uBCCD\uAC8C \uC720\uC9C0\uD574 \uBCF4\uC138\uC694. \uC5ED\uD560 \uD3B8\uC9D1\uC5D0\uC11C \uC5ED\uD560\uB9C8\uB2E4 \uB530\uB85C \uC815\uD560 \uC218\uB3C4 \uC788\uC2B5\uB2C8\uB2E4.", "Tools in the Tool Filter are removed from every subagent of this preset. Remove tools a subagent does not need from its system prompt to keep its context light. Each role can also set its own list in the role editor.", "\u52A0\u5165 Tool Filter \u7684\u5DE5\u5177\u4F1A\u4ECE\u6B64\u9884\u8BBE\u7684\u6240\u6709\u5B50\u4EE3\u7406\u4E2D\u79FB\u9664\u3002\u4ECE\u5B50\u4EE3\u7406\u7684\u7CFB\u7EDF\u63D0\u793A\u4E2D\u79FB\u9664\u5176\u4E0D\u9700\u8981\u7684\u5DE5\u5177\uFF0C\u8BA9\u4E0A\u4E0B\u6587\u4FDD\u6301\u7CBE\u7B80\u3002\u4E5F\u53EF\u4EE5\u5728\u89D2\u8272\u7F16\u8F91\u4E2D\u4E3A\u6BCF\u4E2A\u89D2\u8272\u5355\u72EC\u8BBE\u7F6E\u3002") }),
|
|
908
|
+
!delegates ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Note, { children: t("\uD504\uB86C\uD504\uD2B8\xB7\uB3C4\uAD6C \uD0ED\uC5D0\uC11C subagent_role\uC744 \uC120\uD0DD\uD558\uBA74 \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", "Select subagent_role on the Prompts & tools tab to use the Tool Filter.", "\u5728\u201C\u63D0\u793A\u8BCD\u4E0E\u5DE5\u5177\u201D\u9875\u9009\u62E9 subagent_role \u540E\u5373\u53EF\u4F7F\u7528\u3002") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToolFilterPicker, { label: filterTitle, tools, selected: hiddenTools, onChange: onHiddenToolsChange, t })
|
|
909
|
+
] }),
|
|
910
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
807
911
|
DetailDialog,
|
|
808
912
|
{
|
|
809
913
|
open: role !== void 0,
|
|
810
914
|
title: role?.name || t("\uC0C8 \uC5ED\uD560", "New role", "\u65B0\u89D2\u8272"),
|
|
811
915
|
subtitle: t("\uC5ED\uD560 \uD3B8\uC9D1", "Edit role", "\u7F16\u8F91\u89D2\u8272"),
|
|
812
916
|
onClose: close,
|
|
813
|
-
footer: /* @__PURE__ */ (0,
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
917
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { small: true, onClick: () => {
|
|
815
919
|
onChange(roles.filter((_, index) => index !== selected));
|
|
816
920
|
close();
|
|
817
921
|
}, children: t("\uC5ED\uD560 \uC0AD\uC81C", "Remove role", "\u79FB\u9664\u89D2\u8272") }),
|
|
818
|
-
/* @__PURE__ */ (0,
|
|
922
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { small: true, primary: true, onClick: close, children: t("\uC644\uB8CC", "Done", "\u5B8C\u6210") })
|
|
819
923
|
] }),
|
|
820
|
-
children: role && /* @__PURE__ */ (0,
|
|
821
|
-
/* @__PURE__ */ (0,
|
|
822
|
-
field2(t("\uC774\uB984", "Name", "\u540D\u79F0"), /* @__PURE__ */ (0,
|
|
823
|
-
field2(t("\uC5ED\uD560 ID", "Role", "\u89D2\u8272"), /* @__PURE__ */ (0,
|
|
924
|
+
children: role && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "studio-field-grid", children: [
|
|
926
|
+
field2(t("\uC774\uB984", "Name", "\u540D\u79F0"), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: role.name, onChange: (e) => update2({ name: e.target.value }) })),
|
|
927
|
+
field2(t("\uC5ED\uD560 ID", "Role ID", "\u89D2\u8272 ID"), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "studio-mono", value: role.role, onChange: (e) => update2({ role: e.target.value }) }))
|
|
824
928
|
] }),
|
|
825
|
-
/* @__PURE__ */ (0,
|
|
826
|
-
field2(t("\uBAA8\uB378", "Model", "\u6A21\u578B"), /* @__PURE__ */ (0,
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
828
|
-
role.model !== "inherit" && !model && /* @__PURE__ */ (0,
|
|
929
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "studio-field-grid", children: [
|
|
930
|
+
field2(t("\uBAA8\uB378", "Model", "\u6A21\u578B"), /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: role.model, onChange: (e) => update2({ model: e.target.value, reasoning: "inherit" }), children: [
|
|
931
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "inherit", children: t("\uBD80\uBAA8 \uBAA8\uB378 \uC0AC\uC6A9", "Inherit parent model", "\u7EE7\u627F\u7236\u7EA7\u6A21\u578B") }),
|
|
932
|
+
role.model !== "inherit" && !model && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: role.model, disabled: true, children: [
|
|
829
933
|
role.model,
|
|
830
934
|
" \xB7 ",
|
|
831
|
-
t("\uBAA9\uB85D\uC5D0 \uC5C6\uC74C \xB7 \uBC18\uC601\uD560 \uB54C \uD655\uC778", "Not
|
|
935
|
+
t("\uBAA9\uB85D\uC5D0 \uC5C6\uC74C \xB7 \uBC18\uC601\uD560 \uB54C \uD655\uC778", "Not in list \xB7 checked on apply", "\u76EE\u5F55\u4E2D\u672A\u786E\u8BA4 \xB7 \u5E94\u7528\u65F6\u9A8C\u8BC1")
|
|
832
936
|
] }),
|
|
833
|
-
models.map((model2) => /* @__PURE__ */ (0,
|
|
937
|
+
models.map((model2) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: model2.value, children: model2.label }, model2.value))
|
|
834
938
|
] })),
|
|
835
|
-
field2(t("\uCD94\uB860 \uC218\uC900", "Reasoning", "\u63A8\u7406\u7EA7\u522B"), /* @__PURE__ */ (0,
|
|
836
|
-
/* @__PURE__ */ (0,
|
|
837
|
-
role.reasoning !== "inherit" && !model?.reasoning?.efforts.some((e) => e.id === role.reasoning) && /* @__PURE__ */ (0,
|
|
939
|
+
field2(t("\uCD94\uB860 \uC218\uC900", "Reasoning", "\u63A8\u7406\u7EA7\u522B"), /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: role.reasoning, disabled: !model, onChange: (e) => update2({ reasoning: e.target.value }), children: [
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "inherit", children: role.model === "inherit" ? t("\uBD80\uBAA8 \uC124\uC815 \uC0AC\uC6A9", "Inherit parent setting", "\u7EE7\u627F\u7236\u7EA7\u8BBE\u7F6E") : t("\uBAA8\uB378 \uAE30\uBCF8\uAC12", "Model default", "\u6A21\u578B\u9ED8\u8BA4\u503C") }),
|
|
941
|
+
role.reasoning !== "inherit" && !model?.reasoning?.efforts.some((e) => e.id === role.reasoning) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: role.reasoning, disabled: true, children: [
|
|
838
942
|
role.reasoning,
|
|
839
943
|
" \xB7 ",
|
|
840
|
-
t("\uC9C0\uC6D0 \uC5EC\uBD80 \uD655\uC778 \uD544\uC694", "
|
|
944
|
+
t("\uC9C0\uC6D0 \uC5EC\uBD80 \uD655\uC778 \uD544\uC694", "Support unconfirmed", "\u9700\u786E\u8BA4\u652F\u6301")
|
|
841
945
|
] }),
|
|
842
|
-
model?.reasoning?.efforts.map((e) => /* @__PURE__ */ (0,
|
|
946
|
+
model?.reasoning?.efforts.map((e) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: e.id, children: e.name }, e.id))
|
|
843
947
|
] })),
|
|
844
|
-
field2(t("\uC2DC\uC791 \uBC29\uC2DD", "Spawn mode", "\u751F\u6210\u65B9\u5F0F"), /* @__PURE__ */ (0,
|
|
845
|
-
/* @__PURE__ */ (0,
|
|
846
|
-
/* @__PURE__ */ (0,
|
|
948
|
+
field2(t("\uC2DC\uC791 \uBC29\uC2DD", "Spawn mode", "\u751F\u6210\u65B9\u5F0F"), /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: role.spawn, onChange: (e) => update2({ spawn: e.target.value }), children: [
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "fresh", children: t("\uC0C8 \uB300\uD654 (Fresh)", "New conversation (Fresh)", "\u65B0\u5BF9\u8BDD\uFF08Fresh\uFF09") }),
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "fork", children: t("\uBD80\uBAA8 \uB300\uD654 \uC774\uC5B4\uBC1B\uAE30 (Fork)", "Continue parent (Fork)", "\u7EE7\u627F\u7236\u5BF9\u8BDD\uFF08Fork\uFF09") })
|
|
847
951
|
] }))
|
|
848
952
|
] }),
|
|
849
|
-
|
|
850
|
-
|
|
953
|
+
tools && delegates && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "studio-field", children: [
|
|
954
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: filterTitle }),
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { "aria-label": roleFilterLabel, value: role.toolFilter?.mode ?? "default", onChange: (e) => {
|
|
956
|
+
const mode = e.target.value;
|
|
957
|
+
update2({ toolFilter: mode === "extend" || mode === "replace" ? { mode, deny: [] } : void 0 });
|
|
958
|
+
}, children: [
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "default", children: t(`\uD504\uB9AC\uC14B \uAE30\uBCF8\uAC12 \uC0AC\uC6A9 (${defaultCount}\uAC1C)`, `Use preset default (${defaultCount})`, `\u4F7F\u7528\u9884\u8BBE\u9ED8\u8BA4\u503C\uFF08${defaultCount} \u4E2A\uFF09`) }),
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "extend", children: t("\uAE30\uBCF8\uAC12\uC5D0 \uCD94\uAC00", "Add to preset default", "\u5728\u9ED8\u8BA4\u503C\u57FA\u7840\u4E0A\u6DFB\u52A0") }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "replace", children: t("\uC774 \uC5ED\uD560\uB9CC \uB530\uB85C (\uAE30\uBCF8\uAC12 \uBB34\uC2DC)", "This role only (ignore default)", "\u4EC5\u6B64\u89D2\u8272\uFF08\u5FFD\u7565\u9ED8\u8BA4\u503C\uFF09") })
|
|
962
|
+
] }),
|
|
963
|
+
role.toolFilter?.mode === "extend" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "studio-muted studio-hint", children: t("\uD504\uB9AC\uC14B \uAE30\uBCF8\uAC12\uC758 \uB3C4\uAD6C\uB294 \uC7A0\uAE34 \uCC44\uB85C \uD568\uAED8 \uBE60\uC9D1\uB2C8\uB2E4. \uC774 \uC5ED\uD560\uC5D0\uC11C \uCD94\uAC00\uB85C \uBE84 \uB3C4\uAD6C\uB97C \uACE0\uB974\uC138\uC694. \uAE30\uBCF8\uAC12\uC744 \uBC14\uAFB8\uBA74 \uC774 \uC5ED\uD560\uC5D0\uB3C4 \uBC18\uC601\uB429\uB2C8\uB2E4.", "Preset default tools are locked and stay filtered. Choose the tools this role filters in addition. Changes to the default apply to this role too.", "\u9884\u8BBE\u9ED8\u8BA4\u503C\u4E2D\u7684\u5DE5\u5177\u5DF2\u9501\u5B9A\u5E76\u4E00\u5E76\u6392\u9664\u3002\u8BF7\u9009\u62E9\u6B64\u89D2\u8272\u989D\u5916\u6392\u9664\u7684\u5DE5\u5177\u3002\u9ED8\u8BA4\u503C\u7684\u66F4\u6539\u4E5F\u4F1A\u5E94\u7528\u5230\u6B64\u89D2\u8272\u3002") }),
|
|
964
|
+
role.toolFilter?.mode === "replace" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "studio-muted studio-hint", children: t("\uD504\uB9AC\uC14B \uAE30\uBCF8\uAC12\uC774 \uC774 \uC5ED\uD560\uC5D0\uB294 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC774 \uC5ED\uD560\uC5D0\uC11C \uBE84 \uB3C4\uAD6C\uB9CC \uACE0\uB974\uC138\uC694.", "The preset default does not apply to this role. Choose only the tools this role filters.", "\u9884\u8BBE\u9ED8\u8BA4\u503C\u4E0D\u9002\u7528\u4E8E\u6B64\u89D2\u8272\u3002\u8BF7\u4EC5\u9009\u62E9\u6B64\u89D2\u8272\u6392\u9664\u7684\u5DE5\u5177\u3002") }),
|
|
965
|
+
role.toolFilter && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
966
|
+
ToolFilterPicker,
|
|
967
|
+
{
|
|
968
|
+
label: roleFilterLabel,
|
|
969
|
+
tools,
|
|
970
|
+
selected: role.toolFilter.deny,
|
|
971
|
+
locked: role.toolFilter.mode === "extend" ? hiddenTools : [],
|
|
972
|
+
lockedReason: t("\uD504\uB9AC\uC14B \uAE30\uBCF8\uAC12", "Preset default", "\u9884\u8BBE\u9ED8\u8BA4\u503C"),
|
|
973
|
+
onChange: (deny) => update2({ toolFilter: { mode: role.toolFilter.mode, deny } }),
|
|
974
|
+
t
|
|
975
|
+
}
|
|
976
|
+
)
|
|
977
|
+
] }),
|
|
978
|
+
field2(t("\uC5ED\uD560 \uC9C0\uCE68 (persona)", "Role instructions (persona)", "\u89D2\u8272\u6307\u4EE4\uFF08persona\uFF09"), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("textarea", { rows: 6, value: role.persona, placeholder: defaultPersona, onChange: (e) => update2({ persona: e.target.value }) })),
|
|
979
|
+
!role.persona && defaultPersona && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "studio-muted studio-hint", children: t("\uD750\uB9B0 \uAE00\uC528\uB294 \uD504\uB9AC\uC14B\uC758 \uAE30\uBCF8 persona\uC785\uB2C8\uB2E4. \uBE44\uC6CC \uB450\uBA74 \uC774 \uB0B4\uC6A9\uC774 \uADF8\uB300\uB85C \uC4F0\uC785\uB2C8\uB2E4.", "The dimmed text is the preset default persona; it is used while this field is empty.", "\u6D45\u8272\u6587\u5B57\u662F\u9884\u8BBE\u7684\u9ED8\u8BA4 persona\uFF0C\u7559\u7A7A\u65F6\u4F7F\u7528\u8BE5\u5185\u5BB9\u3002") })
|
|
851
980
|
] })
|
|
852
981
|
}
|
|
853
982
|
)
|
|
854
983
|
] });
|
|
855
984
|
}
|
|
985
|
+
function ToolFilterPicker({ label, tools, selected, onChange, t, locked = [], lockedReason }) {
|
|
986
|
+
const items = tools.map((tool) => locked.includes(tool.name) && lockedReason ? { ...tool, lockedReason } : tool);
|
|
987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
988
|
+
ItemPicker,
|
|
989
|
+
{
|
|
990
|
+
label,
|
|
991
|
+
items,
|
|
992
|
+
selected: selected.filter((name) => tools.some((tool) => tool.name === name) && !locked.includes(name)),
|
|
993
|
+
onChange: (names2) => onChange(names2.filter((name) => !locked.includes(name))),
|
|
994
|
+
hasDetails: () => false,
|
|
995
|
+
labels: { filter: t("\uBCF4\uAE30", "Show", "\u663E\u793A"), search: t("\uB3C4\uAD6C \uAC80\uC0C9", "Search tools", "\u641C\u7D22\u5DE5\u5177"), searchHint: t("\uC774\uB984, \uC124\uBA85\uC73C\uB85C \uAC80\uC0C9", "Search names or descriptions", "\u6309\u540D\u79F0\u6216\u63CF\u8FF0\u641C\u7D22"), all: t("\uC804\uCCB4", "All", "\u5168\u90E8"), selected: t("\uC81C\uC678\uB428", "Filtered", "\u5DF2\u6392\u9664"), modified: t("\uBCC0\uACBD\uB428", "Modified", "\u5DF2\u4FEE\u6539"), settings: t("\uC124\uC815", "Details", "\u8BBE\u7F6E"), done: t("\uC644\uB8CC", "Close", "\u5B8C\u6210"), empty: t("\uC774 \uD504\uB9AC\uC14B\uC5D0\uC11C \uC120\uD0DD\uD55C \uB3C4\uAD6C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.", "This preset selects no tools.", "\u6B64\u9884\u8BBE\u672A\u9009\u62E9\u4EFB\u4F55\u5DE5\u5177\u3002"), noResults: t("\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.", "No matching results.", "\u6CA1\u6709\u5339\u914D\u7ED3\u679C\u3002"), modifiedTag: t("\uBCC0\uACBD\uB428", "Modified", "\u5DF2\u4FEE\u6539"), clear: t("\uC804\uCCB4 \uBCF4\uAE30", "Show all", "\u663E\u793A\u5168\u90E8") }
|
|
996
|
+
}
|
|
997
|
+
);
|
|
998
|
+
}
|
|
856
999
|
|
|
857
1000
|
// src/optimization-prototype.tsx
|
|
858
1001
|
var import_react9 = __toESM(require("react"), 1);
|
|
859
1002
|
|
|
860
1003
|
// src/master-extensions-editor.tsx
|
|
861
|
-
var
|
|
862
|
-
var
|
|
1004
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
1005
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
863
1006
|
function MasterExtensionsEditor({ locale, actions }) {
|
|
864
|
-
const t = (
|
|
865
|
-
const [text, setText] =
|
|
866
|
-
const [error, setError] =
|
|
867
|
-
const [busy, setBusy] =
|
|
868
|
-
const [loaded, setLoaded] =
|
|
869
|
-
|
|
1007
|
+
const t = (ko3, en3, zh3) => locale.startsWith("ko") ? ko3 : locale.startsWith("zh") ? zh3 : en3;
|
|
1008
|
+
const [text, setText] = import_react4.default.useState("[]");
|
|
1009
|
+
const [error, setError] = import_react4.default.useState("");
|
|
1010
|
+
const [busy, setBusy] = import_react4.default.useState(false);
|
|
1011
|
+
const [loaded, setLoaded] = import_react4.default.useState(false);
|
|
1012
|
+
import_react4.default.useEffect(() => {
|
|
870
1013
|
let active = true;
|
|
871
1014
|
if (actions) actions.read().then((value) => {
|
|
872
1015
|
if (active) {
|
|
@@ -880,22 +1023,22 @@ function MasterExtensionsEditor({ locale, actions }) {
|
|
|
880
1023
|
active = false;
|
|
881
1024
|
};
|
|
882
1025
|
}, [actions]);
|
|
883
|
-
return /* @__PURE__ */ (0,
|
|
884
|
-
/* @__PURE__ */ (0,
|
|
885
|
-
/* @__PURE__ */ (0,
|
|
886
|
-
/* @__PURE__ */ (0,
|
|
887
|
-
/* @__PURE__ */ (0,
|
|
888
|
-
/* @__PURE__ */ (0,
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
1026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "studio-page-stack", children: [
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PageHead, { title: t("\uB3C4\uAD6C \uC81C\uACF5\uC790", "Tool providers", "\u5DE5\u5177\u63D0\u4F9B\u8005"), description: t("\uC124\uCE58\uB41C \uD50C\uB7EC\uADF8\uC778\uC758 \uB3C4\uAD6C\uB97C Studio \uB3C4\uAD6C \uBAA9\uB85D\uC5D0 \uB4F1\uB85D\uD569\uB2C8\uB2E4. \uB4F1\uB85D\uD55C \uB3C4\uAD6C\uB294 \uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30\uC5D0\uC11C \uACE0\uB97C \uC218 \uC788\uC2B5\uB2C8\uB2E4.", "Register installed plugin tools in the Studio tool list so presets can select them.", "\u5C06\u5DF2\u5B89\u88C5\u63D2\u4EF6\u7684\u5DE5\u5177\u6CE8\u518C\u5230 Studio \u5DE5\u5177\u5217\u8868\uFF0C\u4F9B\u9884\u8BBE\u9009\u62E9") }),
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Note, { children: t("\uB4F1\uB85D\uD558\uBA74 \uD50C\uB7EC\uADF8\uC778 \uCF54\uB4DC\uAC00 \uC2E4\uD589\uB418\uBBC0\uB85C \uC2E0\uB8B0\uD558\uB294 \uD50C\uB7EC\uADF8\uC778\uB9CC \uCD94\uAC00\uD558\uC138\uC694. \uD328\uD0A4\uC9C0\uB97C \uC124\uCE58\uD558\uC9C0\uB294 \uC54A\uC73C\uBA70, \uC124\uC815\uC740 \uC774 \uCEF4\uD4E8\uD130\uC5D0 \uD3C9\uBB38\uC73C\uB85C \uC800\uC7A5\uB429\uB2C8\uB2E4. \uC774\uBBF8 \uBC18\uC601\uD55C \uD504\uB9AC\uC14B\uC740 \uC790\uB3D9\uC73C\uB85C \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.", "Registering runs the plugin\u2019s code, so add only plugins you trust. Studio does not install packages, and these settings are stored on this computer in plain text. Presets you already applied do not change automatically.", "\u6CE8\u518C\u4F1A\u6267\u884C\u63D2\u4EF6\u4EE3\u7801\uFF0C\u8BF7\u4EC5\u6DFB\u52A0\u53EF\u4FE1\u63D2\u4EF6\u3002Studio \u4E0D\u4F1A\u5B89\u88C5\u8F6F\u4EF6\u5305\uFF0C\u8BBE\u7F6E\u4EE5\u660E\u6587\u4FDD\u5B58\u5728\u672C\u673A\u3002\u5DF2\u5E94\u7528\u7684\u9884\u8BBE\u4E0D\u4F1A\u81EA\u52A8\u6539\u53D8\u3002") }),
|
|
1029
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ol", { className: "studio-steps", children: [
|
|
1030
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: t("\uD50C\uB7EC\uADF8\uC778\uC774 \uD604\uC7AC DSH \uD504\uB85C\uD544\uC5D0 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD569\uB2C8\uB2E4.", "Check that the plugin is installed in this DSH profile.", "\u786E\u8BA4\u63D2\u4EF6\u5DF2\u5B89\u88C5\u5728\u5F53\u524D DSH \u914D\u7F6E\u4E2D\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u5B89\u88C5\u3002") }),
|
|
1031
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: t("\uC544\uB798 \uBC30\uC5F4\uC5D0 id(\uACE0\uC720\uD55C \uC18C\uBB38\uC790 \uC2DD\uBCC4\uC790), name(\uD328\uD0A4\uC9C0 \uC774\uB984), config(\uD50C\uB7EC\uADF8\uC778 \uC124\uC815)\uB97C \uC785\uB825\uD569\uB2C8\uB2E4.", "Add an entry with id (unique lowercase identifier), name (exact package name), and config (public plugin settings).", "\u5728\u6570\u7EC4\u4E2D\u586B\u5199 id\uFF08\u552F\u4E00\u5C0F\u5199\u6807\u8BC6\u7B26\uFF09\u3001name\uFF08\u51C6\u786E\u7684\u8F6F\u4EF6\u5305\u540D\uFF09\u548C config\uFF08\u63D2\u4EF6\u516C\u5F00\u8BBE\u7F6E\uFF09\u3002") }),
|
|
1032
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: t("\uD655\uC778 \uD6C4 \uB4F1\uB85D\uC744 \uB204\uB974\uBA74 \uB3C4\uAD6C \uBAA9\uB85D\uC774 \uAC31\uC2E0\uB429\uB2C8\uB2E4. \uD544\uC694\uD55C \uB3C4\uAD6C\uB97C \uACE8\uB77C \uD504\uB9AC\uC14B\uC744 \uC800\uC7A5\uD558\uC138\uC694.", "Select Validate and update master to refresh the tool list, then choose the tools and save your preset.", "\u9A8C\u8BC1\u5E76\u66F4\u65B0\u4E3B\u9884\u8BBE\u540E\uFF0C\u9009\u62E9\u6240\u9700\u5DE5\u5177\u5E76\u4FDD\u5B58\u9884\u8BBE\u3002") })
|
|
890
1033
|
] }),
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
893
|
-
/* @__PURE__ */ (0,
|
|
894
|
-
/* @__PURE__ */ (0,
|
|
895
|
-
/* @__PURE__ */ (0,
|
|
896
|
-
/* @__PURE__ */ (0,
|
|
1034
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "studio-muted", children: t("\uC608\uC2DC: \uC124\uCE58\uB41C subagent \uD50C\uB7EC\uADF8\uC778\uC744 \uB2E4\uB978 \uB3C4\uAD6C \uC774\uB984\uC73C\uB85C \uB4F1\uB85D", "Example: register the installed subagent provider under a distinct tool name", "\u793A\u4F8B\uFF1A\u4F7F\u7528\u4E0D\u540C\u5DE5\u5177\u540D\u6CE8\u518C\u5DF2\u5B89\u88C5\u7684 subagent \u63D0\u4F9B\u8005") }),
|
|
1035
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { children: JSON.stringify([{ id: "extra-agent", name: "@deepseek-ai/dsh-tool-subagent", config: { provider: "spawn", toolName: "studio_extra_agent" } }], null, 2) }),
|
|
1036
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Note, { children: t("\uBAA9\uB85D \uC804\uCCB4\uAC00 \uC0C8 \uB0B4\uC6A9\uC73C\uB85C \uBC14\uB01D\uB2C8\uB2E4. \uAE30\uC874 \uD56D\uBAA9\uC744 \uC720\uC9C0\uD558\uB824\uBA74 \uBC30\uC5F4\uC5D0 \uB0A8\uACA8 \uB450\uACE0, \uBAA8\uB450 \uC9C0\uC6B0\uB824\uBA74 []\uB97C \uB4F1\uB85D\uD558\uC138\uC694. \uB3C4\uAD6C \uC774\uB984\uC774 \uACB9\uCE58\uC9C0 \uC54A\uAC8C \uD558\uC138\uC694. \uD544\uC694\uD55C \uC11C\uBE44\uC2A4\uAC00 \uC5C6\uB294 \uD50C\uB7EC\uADF8\uC778\uC740 \uD65C\uC131\uD654\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", "Registering replaces the whole list. Keep existing entries in the array to retain them, or register [] to remove them all. Avoid tool names that already exist. A plugin whose required services are missing may fail to activate.", "\u6CE8\u518C\u4F1A\u66FF\u6362\u6574\u4E2A\u5217\u8868\u3002\u4FDD\u7559\u5DF2\u6709\u6761\u76EE\u4EE5\u514D\u5220\u9664\uFF1B\u6CE8\u518C [] \u4F1A\u79FB\u9664\u5168\u90E8\u6761\u76EE\u3002\u907F\u514D\u5DE5\u5177\u91CD\u540D\uFF1B\u7F3A\u5C11\u4F9D\u8D56\u670D\u52A1\u7684\u63D2\u4EF6\u53EF\u80FD\u65E0\u6CD5\u6FC0\u6D3B\u3002") }),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "studio-field", children: [
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("\uB4F1\uB85D \uBAA9\uB85D (JSON)", "Provider list (JSON)", "\u63D0\u4F9B\u8005\u5217\u8868\uFF08JSON\uFF09") }),
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("textarea", { rows: 6, className: "studio-mono", value: text, disabled: !loaded || busy, onChange: (event) => setText(event.target.value) })
|
|
897
1040
|
] }),
|
|
898
|
-
/* @__PURE__ */ (0,
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "studio-inline-actions", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { disabled: !loaded || busy, onClick: async () => {
|
|
899
1042
|
if (!actions) return;
|
|
900
1043
|
setBusy(true);
|
|
901
1044
|
setError("");
|
|
@@ -907,10 +1050,35 @@ function MasterExtensionsEditor({ locale, actions }) {
|
|
|
907
1050
|
setBusy(false);
|
|
908
1051
|
}
|
|
909
1052
|
}, children: t("\uD655\uC778 \uD6C4 \uB4F1\uB85D", "Validate and update master", "\u9A8C\u8BC1\u5E76\u66F4\u65B0\u4E3B\u9884\u8BBE") }) }),
|
|
910
|
-
error && /* @__PURE__ */ (0,
|
|
1053
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { role: "alert", children: error })
|
|
911
1054
|
] });
|
|
912
1055
|
}
|
|
913
1056
|
|
|
1057
|
+
// src/package-name.ts
|
|
1058
|
+
var PACKAGE_NAME = "@matamt-dbg/dsh-studio";
|
|
1059
|
+
var POLICY_PLUGIN = `${PACKAGE_NAME}/policy`;
|
|
1060
|
+
var ROLE_PLUGIN = `${PACKAGE_NAME}/roles`;
|
|
1061
|
+
var BATCH_PLUGIN = `${PACKAGE_NAME}/batch`;
|
|
1062
|
+
var STUDIO_VERSION = "0.2.8";
|
|
1063
|
+
|
|
1064
|
+
// src/delegation.ts
|
|
1065
|
+
var ROLE_TOOL = "subagent_role";
|
|
1066
|
+
var LEGACY_ROLE_TOOL = "studio_role";
|
|
1067
|
+
var GENERIC_DELEGATION_TOOLS = ["subagent", "subagent_fork", "list_subagent_models"];
|
|
1068
|
+
var SUBAGENT_PLUGIN = "@deepseek-ai/dsh-tool-subagent";
|
|
1069
|
+
var isDelegationPlugin = (name) => name === SUBAGENT_PLUGIN || name === ROLE_PLUGIN;
|
|
1070
|
+
var WITHDRAWN_TOOLS = ["task_run"];
|
|
1071
|
+
function delegationTools(tools, hasRoles = false) {
|
|
1072
|
+
const delegates = hasRoles || tools.some((name) => name === ROLE_TOOL || name === LEGACY_ROLE_TOOL || GENERIC_DELEGATION_TOOLS.includes(name));
|
|
1073
|
+
const rest = tools.filter((name) => name !== ROLE_TOOL && name !== LEGACY_ROLE_TOOL && !GENERIC_DELEGATION_TOOLS.includes(name) && !WITHDRAWN_TOOLS.includes(name));
|
|
1074
|
+
return delegates ? [...rest, ROLE_TOOL] : rest;
|
|
1075
|
+
}
|
|
1076
|
+
function renameLegacyRoleKey(entries) {
|
|
1077
|
+
if (!entries || !Object.hasOwn(entries, LEGACY_ROLE_TOOL)) return entries;
|
|
1078
|
+
const { [LEGACY_ROLE_TOOL]: legacy, ...rest } = entries;
|
|
1079
|
+
return Object.hasOwn(rest, ROLE_TOOL) ? rest : { ...rest, [ROLE_TOOL]: legacy };
|
|
1080
|
+
}
|
|
1081
|
+
|
|
914
1082
|
// src/config-editor.tsx
|
|
915
1083
|
var import_react5 = __toESM(require("react"), 1);
|
|
916
1084
|
|
|
@@ -924,63 +1092,6 @@ function hasChangedOverride(base, override) {
|
|
|
924
1092
|
return JSON.stringify(base) !== JSON.stringify(override);
|
|
925
1093
|
}
|
|
926
1094
|
|
|
927
|
-
// src/item-picker.tsx
|
|
928
|
-
var import_react4 = __toESM(require("react"), 1);
|
|
929
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
930
|
-
function ItemPicker({ label, items, selected, onChange, labels, renderDetails, isModified, hasDetails }) {
|
|
931
|
-
const [query, setQuery] = import_react4.default.useState("");
|
|
932
|
-
const [filter, setFilter] = import_react4.default.useState("all");
|
|
933
|
-
const [detail, setDetail] = import_react4.default.useState();
|
|
934
|
-
const chosen = new Set(selected);
|
|
935
|
-
const modified = (name) => chosen.has(name) && (isModified?.(name) ?? false);
|
|
936
|
-
const text = query.trim().toLowerCase();
|
|
937
|
-
const visible = items.filter((item) => (filter === "all" || (filter === "selected" ? chosen.has(item.name) : modified(item.name))) && (!text || `${item.name}
|
|
938
|
-
${item.title ?? ""}
|
|
939
|
-
${item.description}
|
|
940
|
-
${item.searchText ?? ""}`.toLowerCase().includes(text)));
|
|
941
|
-
const counts = { all: items.length, selected: items.filter((item) => chosen.has(item.name)).length, modified: items.filter((item) => modified(item.name)).length };
|
|
942
|
-
const toggle = (name) => onChange(chosen.has(name) ? selected.filter((value) => value !== name) : [...selected, name]);
|
|
943
|
-
const open = items.find((item) => item.name === detail && chosen.has(item.name));
|
|
944
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "studio-picker", children: [
|
|
945
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "studio-picker-bar", children: [
|
|
946
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "search", "aria-label": labels.search, placeholder: labels.searchHint, value: query, onChange: (event) => setQuery(event.target.value) }),
|
|
947
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "studio-picker-filters", role: "radiogroup", "aria-label": labels.filter, children: ["all", "selected", "modified"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", role: "radio", "aria-checked": filter === value, className: "studio-picker-filter", onClick: () => setFilter(value), children: [
|
|
948
|
-
labels[value],
|
|
949
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "studio-count", children: counts[value] })
|
|
950
|
-
] }, value)) })
|
|
951
|
-
] }),
|
|
952
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ul", { className: "studio-picker-list", "aria-label": label, children: [
|
|
953
|
-
visible.map((item) => {
|
|
954
|
-
const on = chosen.has(item.name);
|
|
955
|
-
const blocked = !on && item.disabledReason !== void 0;
|
|
956
|
-
const details = on && renderDetails !== void 0 && (hasDetails?.(item.name) ?? true);
|
|
957
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "studio-picker-row", "data-selected": on, children: [
|
|
958
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", role: "switch", "aria-checked": on, disabled: blocked, className: "studio-picker-toggle", "aria-label": `${item.title ?? item.name}`, onClick: () => toggle(item.name), children: [
|
|
959
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "studio-picker-check", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M3.5 8.5l3 3 6-7", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
960
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "studio-picker-text", children: [
|
|
961
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "studio-picker-title", children: [
|
|
962
|
-
item.title ?? item.name,
|
|
963
|
-
item.subtitle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "studio-picker-subtitle studio-mono", children: item.subtitle })
|
|
964
|
-
] }),
|
|
965
|
-
(item.disabledReason && !on ? item.disabledReason : item.description) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "studio-picker-description", children: item.disabledReason && !on ? item.disabledReason : item.description })
|
|
966
|
-
] })
|
|
967
|
-
] }),
|
|
968
|
-
modified(item.name) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "studio-badge", "data-tone": "info", "data-studio-modified": "true", children: labels.modifiedTag }),
|
|
969
|
-
details && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { small: true, "aria-label": `${labels.settings}: ${item.name}`, "aria-haspopup": "dialog", onClick: () => setDetail(item.name), children: labels.settings })
|
|
970
|
-
] }, item.name);
|
|
971
|
-
}),
|
|
972
|
-
!visible.length && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "studio-picker-empty", role: "status", children: [
|
|
973
|
-
text ? labels.noResults : labels.empty,
|
|
974
|
-
(text || filter !== "all") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { small: true, onClick: () => {
|
|
975
|
-
setQuery("");
|
|
976
|
-
setFilter("all");
|
|
977
|
-
}, children: labels.clear })
|
|
978
|
-
] })
|
|
979
|
-
] }),
|
|
980
|
-
renderDetails && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DetailDialog, { open: open !== void 0, title: open?.title ?? open?.name, subtitle: open?.subtitle, closeLabel: labels.done, onClose: () => setDetail(void 0), children: open && renderDetails(open.name) })
|
|
981
|
-
] });
|
|
982
|
-
}
|
|
983
|
-
|
|
984
1095
|
// src/config-editor.tsx
|
|
985
1096
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
986
1097
|
var copy = {
|
|
@@ -988,10 +1099,11 @@ var copy = {
|
|
|
988
1099
|
list: "Configs",
|
|
989
1100
|
reset: "Reset override",
|
|
990
1101
|
unavailable: "Schema unavailable; editing is disabled.",
|
|
1102
|
+
delegated: "Merged into subagent_role. Configure subagents in the Subagent settings tab.",
|
|
991
1103
|
inherited: "Base value (not overridden)",
|
|
992
1104
|
overridden: "Override",
|
|
993
1105
|
unset: "Not set",
|
|
994
|
-
unsupported: "This schema type is not yet supported by the form. Existing values are preserved;
|
|
1106
|
+
unsupported: "This schema type is not yet supported by the form. Existing values are preserved; turn off the Config to reset them.",
|
|
995
1107
|
json: "Config",
|
|
996
1108
|
invalid: "Enter valid JSON.",
|
|
997
1109
|
object: "Enter a JSON object.",
|
|
@@ -1003,6 +1115,7 @@ var copy = {
|
|
|
1003
1115
|
list: "Config",
|
|
1004
1116
|
reset: "\uAE30\uBCF8\uAC12\uC73C\uB85C",
|
|
1005
1117
|
unavailable: "\uC2A4\uD0A4\uB9C8\uB97C \uC77D\uC744 \uC218 \uC5C6\uC5B4 \uD3B8\uC9D1\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
1118
|
+
delegated: "subagent_role\uB85C \uD1B5\uD569\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8 \uD0ED\uC5D0\uC11C \uC124\uC815\uD558\uC138\uC694.",
|
|
1006
1119
|
inherited: "\uAE30\uBCF8\uAC12",
|
|
1007
1120
|
overridden: "\uBCC0\uACBD\uB428",
|
|
1008
1121
|
unset: "\uBBF8\uC124\uC815",
|
|
@@ -1018,6 +1131,7 @@ var copy = {
|
|
|
1018
1131
|
list: "Config",
|
|
1019
1132
|
reset: "\u91CD\u7F6E\u8986\u76D6",
|
|
1020
1133
|
unavailable: "\u67B6\u6784\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u7F16\u8F91",
|
|
1134
|
+
delegated: "\u5DF2\u5408\u5E76\u5230 subagent_role\u3002\u8BF7\u5728\u5B50\u4EE3\u7406\u8BBE\u7F6E\u9875\u4E2D\u914D\u7F6E\u3002",
|
|
1021
1135
|
inherited: "\u57FA\u7840\u503C\uFF08\u672A\u8986\u76D6\uFF09",
|
|
1022
1136
|
overridden: "\u8986\u76D6",
|
|
1023
1137
|
unset: "\u672A\u8BBE\u7F6E",
|
|
@@ -1339,7 +1453,7 @@ function ConfigEditor({ entries, value, onChange, locale }) {
|
|
|
1339
1453
|
subtitle: entry.id,
|
|
1340
1454
|
description: "",
|
|
1341
1455
|
searchText: JSON.stringify(entry.schema ?? {}),
|
|
1342
|
-
...entry.error || !entry.schema ? { disabledReason: entry.error || labels.unavailable } : {}
|
|
1456
|
+
...isDelegationPlugin(entry.name) ? { disabledReason: labels.delegated } : entry.error || !entry.schema ? { disabledReason: entry.error || labels.unavailable } : {}
|
|
1343
1457
|
})),
|
|
1344
1458
|
...Object.keys(value).filter((id) => !entries.some((entry) => entry.id === id)).map((id) => ({ name: id, title: id, description: labels.unavailable }))
|
|
1345
1459
|
];
|
|
@@ -1374,7 +1488,7 @@ var import_react6 = __toESM(require("react"), 1);
|
|
|
1374
1488
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1375
1489
|
var message = (error) => error instanceof Error ? error.message : String(error);
|
|
1376
1490
|
function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
1377
|
-
const t = (
|
|
1491
|
+
const t = (ko3, en3, zh3) => locale.startsWith("ko") ? ko3 : locale.startsWith("zh") ? zh3 : en3;
|
|
1378
1492
|
const [load, setLoad] = import_react6.default.useState({ phase: "loading" });
|
|
1379
1493
|
const [action, setAction] = import_react6.default.useState();
|
|
1380
1494
|
const [deleting, setDeleting] = import_react6.default.useState();
|
|
@@ -1419,7 +1533,7 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1419
1533
|
const warnings = [...items.reduce((groups, item) => item.applyWarning ? groups.set(item.applyWarning, [...groups.get(item.applyWarning) ?? [], item.name]) : groups, /* @__PURE__ */ new Map())];
|
|
1420
1534
|
const retry = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { small: true, disabled: load.phase === "loading", onClick: () => void refresh(), children: t("\uB2E4\uC2DC \uC2DC\uB3C4", "Retry", "\u91CD\u8BD5") });
|
|
1421
1535
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1422
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PageHead, { title: t("\uD504\uB9AC\uC14B \uBAA9\uB85D", "Preset list", "\u9884\u8BBE\u5217\u8868"), description: t("\
|
|
1536
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PageHead, { title: t("\uD504\uB9AC\uC14B \uBAA9\uB85D", "Preset list", "\u9884\u8BBE\u5217\u8868"), description: t("\uC0C8 \uC138\uC158\uC5D0 \uC801\uC6A9\uD558\uB824\uBA74 DSH\uC5D0 \uBC18\uC601\uD574 \uC8FC\uC138\uC694. \uC774\uBBF8 \uC2E4\uD589 \uC911\uC778 \uC138\uC158\uC5D0\uB294 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.", "Apply to DSH to use these settings in new sessions. Changes do not affect sessions that are already running.", "\u8BF7\u5E94\u7528\u5230 DSH\uFF0C\u4EE5\u4FBF\u5728\u65B0\u4F1A\u8BDD\u4E2D\u4F7F\u7528\u8FD9\u4E9B\u8BBE\u7F6E\u3002\u66F4\u6539\u4E0D\u4F1A\u5F71\u54CD\u6B63\u5728\u8FD0\u884C\u7684\u4F1A\u8BDD\u3002"), actions: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { disabled: busy || !api || load.phase === "loading", onClick: () => void refresh(), children: load.phase === "loading" && load.items ? t("\uC0C8\uB85C\uACE0\uCE68 \uC911\u2026", "Refreshing\u2026", "\u5237\u65B0\u4E2D\u2026") : t("\uC0C8\uB85C\uACE0\uCE68", "Refresh", "\u5237\u65B0") }) }),
|
|
1423
1537
|
!api && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Notice, { children: t("Studio \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC544 \uD504\uB9AC\uC14B\uC744 \uBD88\uB7EC\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", "Presets are unavailable because the Studio Host API is not connected.", "Studio Host API \u672A\u8FDE\u63A5\uFF0C\u65E0\u6CD5\u52A0\u8F7D\u9884\u8BBE") }),
|
|
1424
1538
|
api && load.phase === "loading" && !load.items && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "status", className: "studio-muted", children: t("\uD504\uB9AC\uC14B\uC744 \uBD88\uB7EC\uC624\uB294 \uC911\u2026", "Loading presets\u2026", "\u6B63\u5728\u52A0\u8F7D\u9884\u8BBE\u2026") }),
|
|
1425
1539
|
load.phase === "failed" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Notice, { action: retry, children: load.items ? t(`\uBAA9\uB85D\uC744 \uC0C8\uB85C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD574 \uC774\uC804 \uBAA9\uB85D\uC744 \uD45C\uC2DC\uD569\uB2C8\uB2E4. (${load.error})`, `Could not reload the list. Showing the last loaded list. (${load.error})`, `\u65E0\u6CD5\u91CD\u65B0\u52A0\u8F7D\u5217\u8868\uFF0C\u6B63\u5728\u663E\u793A\u4E0A\u6B21\u52A0\u8F7D\u7684\u5217\u8868\uFF08${load.error}\uFF09`) : t(`\uD504\uB9AC\uC14B \uBAA9\uB85D\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC800\uC7A5\uB41C \uD504\uB9AC\uC14B\uC5D0\uB294 \uC601\uD5A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. (${load.error})`, `Could not load presets. Saved presets were not changed. (${load.error})`, `\u65E0\u6CD5\u52A0\u8F7D\u9884\u8BBE\uFF0C\u5DF2\u4FDD\u5B58\u7684\u9884\u8BBE\u672A\u88AB\u66F4\u6539\uFF08${load.error}\uFF09`) }),
|
|
@@ -1429,7 +1543,7 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1429
1543
|
action.error,
|
|
1430
1544
|
")"
|
|
1431
1545
|
] }),
|
|
1432
|
-
load.phase === "ready" && !items.length && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "status", className: "studio-muted", children: t("\uC800\uC7A5\uB41C \uD504\uB9AC\uC14B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30\uC5D0\uC11C \uC0C8\uB85C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694.", "No saved presets. Create
|
|
1546
|
+
load.phase === "ready" && !items.length && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "status", className: "studio-muted", children: t("\uC800\uC7A5\uB41C \uD504\uB9AC\uC14B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30\uC5D0\uC11C \uC0C8\uB85C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694.", "No saved presets. Use Create preset to make one.", "\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u9884\u8BBE\u3002\u8BF7\u4ECE\u521B\u5EFA\u9884\u8BBE\u83DC\u5355\u5F00\u59CB\u3002") }),
|
|
1433
1547
|
warnings.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "studio-preset-warnings", "aria-label": t("\uC8FC\uC758\uC0AC\uD56D", "Notices", "\u6CE8\u610F\u4E8B\u9879"), children: warnings.map(([text, names2]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { children: [
|
|
1434
1548
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { tone: "warning", children: t("\uC8FC\uC758", "Notice", "\u6CE8\u610F") }),
|
|
1435
1549
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
|
|
@@ -1437,7 +1551,7 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1437
1551
|
" ",
|
|
1438
1552
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "studio-card-meta", children: [
|
|
1439
1553
|
"(",
|
|
1440
|
-
t("\
|
|
1554
|
+
t("\uB300\uC0C1", "Affects", "\u6D89\u53CA"),
|
|
1441
1555
|
": ",
|
|
1442
1556
|
names2.join(", "),
|
|
1443
1557
|
")"
|
|
@@ -1451,7 +1565,7 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1451
1565
|
item.template && !item.readOnly && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { tone: "info", children: t("\uAE30\uBCF8 \uC81C\uACF5", "Built-in", "\u5185\u7F6E") }),
|
|
1452
1566
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { tone: tone[item.status], children: status(item) })
|
|
1453
1567
|
] }),
|
|
1454
|
-
item.template ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-card-text", children: t("Studio\uAC00 \uAD8C\uC7A5\uD558\uB294 \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8\uC6A9 \
|
|
1568
|
+
item.template ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-card-text", children: t("Studio\uAC00 \uAD8C\uC7A5\uD558\uB294 \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8\uC6A9 \uAD6C\uC131\uC785\uB2C8\uB2E4. \uACE0\uCE58\uB824\uBA74 \uBCF5\uC0AC\uD574\uC11C \uC4F0\uC138\uC694.", "Studio\u2019s recommended setup for coding agents. Create a copy to customize it.", "Studio \u63A8\u8350\u7684\u7F16\u7801\u4EE3\u7406\u914D\u7F6E\u3002\u5982\u9700\u4FEE\u6539\uFF0C\u8BF7\u521B\u5EFA\u526F\u672C") }) : item.description && !item.readOnly && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-card-text", children: item.description }),
|
|
1455
1569
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "studio-card-meta", children: [
|
|
1456
1570
|
t("\uB3C4\uAD6C", "Tools", "\u5DE5\u5177"),
|
|
1457
1571
|
" ",
|
|
@@ -1461,7 +1575,7 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1461
1575
|
" ",
|
|
1462
1576
|
Array.isArray(item.agents) ? item.agents.length : 0
|
|
1463
1577
|
] }),
|
|
1464
|
-
item.readOnly ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-card-meta studio-card-note", children: t("
|
|
1578
|
+
item.readOnly ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-card-meta studio-card-note", children: t("\uC774 \uD504\uB85C\uD544\uC5D0\uC11C \uC4F8 \uC218 \uC788\uB294 \uBAA8\uB4E0 \uB3C4\uAD6C\uB97C \uB2F4\uC740 \uAE30\uC900 \uD504\uB9AC\uC14B\uC785\uB2C8\uB2E4. \uD3B8\uC9D1\uD558\uAC70\uB098 \uC0AD\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", "Reference preset with every tool available in this profile. It cannot be edited or deleted.", "\u5305\u542B\u6B64\u914D\u7F6E\u6587\u4EF6\u4E2D\u6240\u6709\u53EF\u7528\u5DE5\u5177\u7684\u57FA\u51C6\u9884\u8BBE\uFF0C\u65E0\u6CD5\u7F16\u8F91\u6216\u5220\u9664") }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "studio-card-footer", children: [
|
|
1465
1579
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { small: true, disabled: busy || item.readOnly || item.template || !onEdit, title: item.template ? t("\uAE30\uBCF8 \uC81C\uACF5 \uD504\uB9AC\uC14B\uC740 \uD3B8\uC9D1\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBCF5\uC0AC\uD574\uC11C \uACE0\uCCD0 \uC4F0\uC138\uC694.", "Built-in presets cannot be edited. Create a copy to customize it.", "\u5185\u7F6E\u9884\u8BBE\u65E0\u6CD5\u7F16\u8F91\uFF0C\u8BF7\u521B\u5EFA\u526F\u672C\u540E\u4FEE\u6539") : void 0, onClick: () => onEdit?.(item), children: t("\uD3B8\uC9D1", "Edit", "\u7F16\u8F91") }),
|
|
1466
1580
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { small: true, disabled: busy || !onCopy, onClick: () => onCopy?.(item), children: t("\uBCF5\uC0AC", "Create copy", "\u521B\u5EFA\u526F\u672C") }),
|
|
1467
1581
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { small: true, disabled: busy || !api || item.readOnly || item.nonDeletable, title: item.nonDeletable ? t("\uAE30\uBCF8 \uC81C\uACF5 \uD504\uB9AC\uC14B\uC740 \uC0AD\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", "Built-in presets cannot be deleted.", "\u5185\u7F6E\u9884\u8BBE\u65E0\u6CD5\u5220\u9664") : void 0, onClick: () => {
|
|
@@ -1497,43 +1611,46 @@ function PresetList({ locale, api, revision, onEdit, onCopy }) {
|
|
|
1497
1611
|
void run(target.id, "delete", () => api.delete(target.id)).then(() => setDeleting(void 0));
|
|
1498
1612
|
}, children: t("\uC0AD\uC81C \uD655\uC778", "Confirm delete", "\u786E\u8BA4\u5220\u9664") })
|
|
1499
1613
|
] }),
|
|
1500
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-muted", children: t("\uC800\uC7A5\uB41C \uD504\uB9AC\uC14B\uACFC DSH\uC5D0 \uBC18\uC601\uB41C \uD504\uB9AC\uC14B\uC744 \uD568\uAED8 \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uAE30\uC874 \uB300\uD654\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4.", "
|
|
1614
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "studio-muted", children: t("\uC800\uC7A5\uB41C \uD504\uB9AC\uC14B\uACFC DSH\uC5D0 \uBC18\uC601\uB41C \uD504\uB9AC\uC14B\uC744 \uD568\uAED8 \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uAE30\uC874 \uB300\uD654\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4.", "Deletes the saved preset and removes it from DSH. Existing conversations are kept.", "\u5220\u9664\u5DF2\u4FDD\u5B58\u9884\u8BBE\u53CA Studio \u6CE8\u518C\u7684 DSH \u9884\u8BBE\uFF0C\u4E0D\u5220\u9664\u73B0\u6709\u5BF9\u8BDD\u3002") })
|
|
1501
1615
|
}
|
|
1502
1616
|
)
|
|
1503
1617
|
] });
|
|
1504
1618
|
}
|
|
1505
1619
|
|
|
1506
|
-
// src/package-name.ts
|
|
1507
|
-
var PACKAGE_NAME = "@matamt-dbg/dsh-studio";
|
|
1508
|
-
var POLICY_PLUGIN = `${PACKAGE_NAME}/policy`;
|
|
1509
|
-
var ROLE_PLUGIN = `${PACKAGE_NAME}/roles`;
|
|
1510
|
-
var BATCH_PLUGIN = `${PACKAGE_NAME}/batch`;
|
|
1511
|
-
|
|
1512
|
-
// src/delegation.ts
|
|
1513
|
-
var ROLE_TOOL = "subagent_role";
|
|
1514
|
-
var LEGACY_ROLE_TOOL = "studio_role";
|
|
1515
|
-
var GENERIC_DELEGATION_TOOLS = ["subagent", "subagent_fork", "list_subagent_models"];
|
|
1516
|
-
var WITHDRAWN_TOOLS = ["task_run"];
|
|
1517
|
-
function delegationTools(tools, hasRoles = false) {
|
|
1518
|
-
const delegates = hasRoles || tools.some((name) => name === ROLE_TOOL || name === LEGACY_ROLE_TOOL || GENERIC_DELEGATION_TOOLS.includes(name));
|
|
1519
|
-
const rest = tools.filter((name) => name !== ROLE_TOOL && name !== LEGACY_ROLE_TOOL && !GENERIC_DELEGATION_TOOLS.includes(name) && !WITHDRAWN_TOOLS.includes(name));
|
|
1520
|
-
return delegates ? [...rest, ROLE_TOOL] : rest;
|
|
1521
|
-
}
|
|
1522
|
-
function renameLegacyRoleKey(entries) {
|
|
1523
|
-
if (!entries || !Object.hasOwn(entries, LEGACY_ROLE_TOOL)) return entries;
|
|
1524
|
-
const { [LEGACY_ROLE_TOOL]: legacy, ...rest } = entries;
|
|
1525
|
-
return Object.hasOwn(rest, ROLE_TOOL) ? rest : { ...rest, [ROLE_TOOL]: legacy };
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
1620
|
// src/optimized-preset.ts
|
|
1529
1621
|
var BUILTIN_TOOL_PRESETS = ["standard", "ptc", "minimal", "cordis"];
|
|
1622
|
+
var OPTIMIZED_TOOLS = [
|
|
1623
|
+
"read_batch",
|
|
1624
|
+
"read",
|
|
1625
|
+
"write",
|
|
1626
|
+
"edit",
|
|
1627
|
+
"glob",
|
|
1628
|
+
"grep",
|
|
1629
|
+
"job_output",
|
|
1630
|
+
"job_list",
|
|
1631
|
+
"job_kill",
|
|
1632
|
+
"skill",
|
|
1633
|
+
"ask_user_question",
|
|
1634
|
+
"web_search",
|
|
1635
|
+
"web_fetch",
|
|
1636
|
+
"present",
|
|
1637
|
+
"bash",
|
|
1638
|
+
"read_image",
|
|
1639
|
+
"exit_plan_mode",
|
|
1640
|
+
"send_message",
|
|
1641
|
+
"interrupt_agent",
|
|
1642
|
+
"list_agents",
|
|
1643
|
+
"workflow",
|
|
1644
|
+
"subagent_role"
|
|
1645
|
+
];
|
|
1646
|
+
var ALLOWED_TOOLS = /* @__PURE__ */ new Set([...OPTIMIZED_TOOLS, ...GENERIC_DELEGATION_TOOLS, LEGACY_ROLE_TOOL]);
|
|
1530
1647
|
|
|
1531
1648
|
// src/prompt-tools-prototype.tsx
|
|
1532
1649
|
var import_react7 = __toESM(require("react"), 1);
|
|
1533
1650
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1534
1651
|
var defaultProvidedTools = [];
|
|
1535
1652
|
function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProvidedChange, catalog, catalogError, onPreview, onRequestChange, initialRequest }) {
|
|
1536
|
-
const t = (
|
|
1653
|
+
const t = (ko3, en3, zh3) => locale.startsWith("ko") ? ko3 : locale.startsWith("zh") ? zh3 : en3;
|
|
1537
1654
|
const base = initialRequest?.preset ?? "studio-master";
|
|
1538
1655
|
const [toolOverrides, setToolOverrides] = import_react7.default.useState(renameLegacyRoleKey(initialRequest?.toolOverrides) ?? {});
|
|
1539
1656
|
const [sections, setSections] = import_react7.default.useState(initialRequest?.sections ?? {});
|
|
@@ -1568,7 +1685,8 @@ function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProv
|
|
|
1568
1685
|
onRequestChange?.(request);
|
|
1569
1686
|
}, [requestKey, onRequestChange]);
|
|
1570
1687
|
const labels = { filter: t("\uBCF4\uAE30", "Show", "\u663E\u793A"), search: t("\uB3C4\uAD6C \uAC80\uC0C9", "Search tools", "\u641C\u7D22\u5DE5\u5177"), searchHint: t("\uC774\uB984, \uC124\uBA85, \uC778\uC790\uB85C \uAC80\uC0C9", "Search names, descriptions or parameters", "\u6309\u540D\u79F0\u3001\u63CF\u8FF0\u6216\u53C2\u6570\u641C\u7D22"), all: t("\uC804\uCCB4", "All", "\u5168\u90E8"), selected: t("\uC120\uD0DD\uB428", "Selected", "\u5DF2\u9009"), modified: t("\uBCC0\uACBD\uB428", "Modified", "\u5DF2\u4FEE\u6539"), settings: t("\uC124\uC815", "Details", "\u8BE6\u60C5"), done: t("\uC644\uB8CC", "Close", "\u5173\u95ED"), empty: t("\uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.", "No items", "\u65E0\u9879\u76EE"), noResults: t("\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.", "No matching results.", "\u6CA1\u6709\u5339\u914D\u7ED3\u679C\u3002"), modifiedTag: t("\uBCC0\uACBD\uB428", "Modified", "\u5DF2\u4FEE\u6539"), clear: t("\uC804\uCCB4 \uBCF4\uAE30", "Show all", "\u663E\u793A\u5168\u90E8") };
|
|
1571
|
-
const
|
|
1688
|
+
const unsupportedToolReason = t("\uD604\uC7AC Studio\uC5D0\uC11C run_code\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. PTC\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 DSH\uC758 PTC \uD504\uB9AC\uC14B\uC73C\uB85C \uC0C8 \uC138\uC158\uC744 \uC2DC\uC791\uD574 \uC8FC\uC138\uC694. \uC774\uBBF8 \uC120\uD0DD\uB41C \uACBD\uC6B0\uC5D0\uB294 \uD574\uC81C\uD574 \uC8FC\uC138\uC694.", "Studio does not currently support run_code. To use PTC, start a new session with DSH\u2019s PTC preset. If run_code is already selected, deselect it.", "Studio \u76EE\u524D\u4E0D\u652F\u6301 run_code\u3002\u5982\u9700\u4F7F\u7528 PTC\uFF0C\u8BF7\u4F7F\u7528 DSH \u7684 PTC \u9884\u8BBE\u542F\u52A8\u65B0\u4F1A\u8BDD\u3002\u82E5\u5DF2\u9009\u62E9 run_code\uFF0C\u8BF7\u53D6\u6D88\u9009\u62E9\u3002");
|
|
1689
|
+
const presetTools = (presetId) => delegationTools(presets.find((p) => p.id === presetId)?.tools.map((tool) => tool.name) ?? []).filter((name) => name !== "run_code");
|
|
1572
1690
|
const togglePreset = (presetId) => {
|
|
1573
1691
|
const names2 = presetTools(presetId);
|
|
1574
1692
|
onProvidedChange(includesPreset(presetId) ? provided.filter((name) => !names2.includes(name)) : [.../* @__PURE__ */ new Set([...provided, ...names2])]);
|
|
@@ -1600,7 +1718,7 @@ function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProv
|
|
|
1600
1718
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react7.default.Fragment, { children: [
|
|
1601
1719
|
catalogError ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Note, { children: catalogError }) : !catalog ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Note, { children: t("\uBD88\uB7EC\uC624\uB294 \uC911\u2026", "Loading\u2026", "\u6B63\u5728\u52A0\u8F7D\u2026") }) : null,
|
|
1602
1720
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "studio-form-section", children: [
|
|
1603
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionHead, { title: t("\uD504\uB86C\uD504\uD2B8", "Prompt composition", "\u63D0\u793A\u8BCD\u7EC4\u88C5"), description: t("\uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C \uC804\uB2EC\uD560 \uC9C0\uCE68\uC744 \uD3B8\uC9D1\uD569\uB2C8\uB2E4. \uBBF8\uB9AC\uBCF4\uAE30\uB85C \uC870\uB9BD \uACB0\uACFC\uB97C \uD655\uC778\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", "Edit
|
|
1721
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionHead, { title: t("\uD504\uB86C\uD504\uD2B8", "Prompt composition", "\u63D0\u793A\u8BCD\u7EC4\u88C5"), description: t("\uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C \uC804\uB2EC\uD560 \uC9C0\uCE68\uC744 \uD3B8\uC9D1\uD569\uB2C8\uB2E4. \uBBF8\uB9AC\uBCF4\uAE30\uB85C \uC870\uB9BD \uACB0\uACFC\uB97C \uD655\uC778\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", "Edit the instructions the agent receives, then preview the assembled result.", "\u7F16\u8F91 Persona \u4E0E Studio \u4E13\u7528\u6307\u4EE4\uFF0C\u5E76\u9884\u89C8\u7EC4\u88C5\u7ED3\u679C\u3002"), actions: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { small: true, disabled: !onPreview || !current || busy, onClick: () => void preview(), children: busy ? t("\uC870\uB9BD \uC911\u2026", "Assembling\u2026", "\u7EC4\u88C5\u4E2D\u2026") : t("\uD504\uB86C\uD504\uD2B8 \uBBF8\uB9AC\uBCF4\uAE30", "Preview prompt", "\u9884\u89C8\u63D0\u793A\u8BCD") }) }),
|
|
1604
1722
|
["prefix", "suffix"].map((key) => {
|
|
1605
1723
|
const name = providers[0];
|
|
1606
1724
|
const config = providerConfigs[name] ?? {};
|
|
@@ -1625,12 +1743,12 @@ function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProv
|
|
|
1625
1743
|
] })
|
|
1626
1744
|
] }),
|
|
1627
1745
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "studio-form-section", children: [
|
|
1628
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionHead, { title: t("\uB3C4\uAD6C", "Provided tools", "\u63D0\u4F9B\u7684\u5DE5\u5177"), description: t("\uC5D0\uC774\uC804\uD2B8\uAC00 \uC4F8 \uB3C4\uAD6C\uB97C \uACE0\uB985\uB2C8\uB2E4. \uC124\uC815\uC5D0\uC11C \uBAA8\uB378\uC5D0 \uBCF4\uC774\uB294 \uC124\uBA85\uC744 \uBC14\uAFC0 \uC218 \uC788\uC73C\uBA70, \uB3C4\uAD6C \uB3D9\uC791\uC740 \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.", "Choose tools. Details
|
|
1746
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionHead, { title: t("\uB3C4\uAD6C", "Provided tools", "\u63D0\u4F9B\u7684\u5DE5\u5177"), description: t("\uC5D0\uC774\uC804\uD2B8\uAC00 \uC4F8 \uB3C4\uAD6C\uB97C \uACE0\uB985\uB2C8\uB2E4. \uC124\uC815\uC5D0\uC11C \uBAA8\uB378\uC5D0 \uBCF4\uC774\uB294 \uC124\uBA85\uC744 \uBC14\uAFC0 \uC218 \uC788\uC73C\uBA70, \uB3C4\uAD6C \uB3D9\uC791\uC740 \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.", "Choose the tools the agent can use. Details changes only the descriptions the model sees; tool behavior stays the same.", "\u9009\u62E9\u5DE5\u5177\u3002\u8BE6\u60C5\u53EA\u7F16\u8F91\u6A21\u578B\u53EF\u89C1\u7684\u63CF\u8FF0\uFF0C\u5DE5\u5177\u884C\u4E3A\u4E0D\u53D8\u3002") }),
|
|
1629
1747
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "studio-field", children: [
|
|
1630
1748
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: t("\uAE30\uBCF8 \uD504\uB9AC\uC14B\uC5D0\uC11C \uD55C \uBC88\uC5D0 \uCD94\uAC00", "Include a built-in preset tool set", "\u5F15\u5165\u5185\u7F6E\u9884\u8BBE\u5DE5\u5177\u96C6") }),
|
|
1631
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "studio-inline-actions", children: toolSources.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { small: true, disabled: !!p.error, "aria-pressed": includesPreset(p.id), onClick: () => togglePreset(p.id), children: p.id === "cordis" ? "creator (cordis)" : p.id }, p.id)) })
|
|
1749
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "studio-inline-actions", children: toolSources.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { small: true, disabled: !!p.error || !presetTools(p.id).length, "aria-pressed": includesPreset(p.id), onClick: () => togglePreset(p.id), children: p.id === "cordis" ? "creator (cordis)" : p.id }, p.id)) })
|
|
1632
1750
|
] }),
|
|
1633
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ItemPicker, { label: t("\uB3C4\uAD6C", "Provided tools", "\u63D0\u4F9B\u7684\u5DE5\u5177"), items: [...tools.map((tool) => ({ ...tool, searchText: JSON.stringify(tool.parameters), ...GENERIC_DELEGATION_TOOLS.includes(tool.name) ? { disabledReason: t(`${ROLE_TOOL}\uB85C \uD1B5\uD569\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8 \uC704\uC784\uC740 ${ROLE_TOOL}\uC744 \uC120\uD0DD\uD558\uC138\uC694.`, `Merged into ${ROLE_TOOL}. Select ${ROLE_TOOL} for subagent delegation.`, `\u5DF2\u5408\u5E76\u5230 ${ROLE_TOOL}\u3002\u8BF7\u9009\u62E9 ${ROLE_TOOL} \u8FDB\u884C\u5B50\u4EE3\u7406\u59D4\u6D3E\u3002`) } : {} })), ...provided.filter((name) => !tools.some((tool) => tool.name === name)).map((name) => ({ name, description: t("\uD604\uC7AC \
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ItemPicker, { label: t("\uB3C4\uAD6C", "Provided tools", "\u63D0\u4F9B\u7684\u5DE5\u5177"), items: [...tools.map((tool) => ({ ...tool, searchText: JSON.stringify(tool.parameters), ...tool.name === "run_code" ? { description: unsupportedToolReason, disabledReason: unsupportedToolReason } : {}, ...GENERIC_DELEGATION_TOOLS.includes(tool.name) ? { disabledReason: t(`${ROLE_TOOL}\uB85C \uD1B5\uD569\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8 \uC704\uC784\uC740 ${ROLE_TOOL}\uC744 \uC120\uD0DD\uD558\uC138\uC694.`, `Merged into ${ROLE_TOOL}. Select ${ROLE_TOOL} for subagent delegation.`, `\u5DF2\u5408\u5E76\u5230 ${ROLE_TOOL}\u3002\u8BF7\u9009\u62E9 ${ROLE_TOOL} \u8FDB\u884C\u5B50\u4EE3\u7406\u59D4\u6D3E\u3002`) } : {} })), ...provided.filter((name) => !tools.some((tool) => tool.name === name)).map((name) => ({ name, description: name === "run_code" ? unsupportedToolReason : t("\uD604\uC7AC \uD504\uB85C\uD544\uC5D0 \uC5C6\uB294 \uB3C4\uAD6C\uC785\uB2C8\uB2E4. \uC774\uB300\uB85C \uBC18\uC601\uD558\uBA74 \uC2E4\uD328\uD569\uB2C8\uB2E4.", "Not available in this profile. Applying will fail.", "\u5F53\u524D\u914D\u7F6E\u6587\u4EF6\u4E2D\u6CA1\u6709\u6B64\u5DE5\u5177\uFF0C\u76F4\u63A5\u5E94\u7528\u4F1A\u5931\u8D25\u3002"), ...name === "run_code" ? { disabledReason: unsupportedToolReason } : {} }))], selected: provided, onChange: changeTools, labels, hasDetails: (name) => name !== "run_code", isModified: (name) => {
|
|
1634
1752
|
const tool = tools.find((item) => item.name === name);
|
|
1635
1753
|
const override = toolOverrides[name];
|
|
1636
1754
|
const parameters = parameterFields(tool?.parameters);
|
|
@@ -1676,7 +1794,7 @@ function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProv
|
|
|
1676
1794
|
const next = { ...toolOverrides };
|
|
1677
1795
|
delete next[name];
|
|
1678
1796
|
setToolOverrides(next);
|
|
1679
|
-
}, children: t("\uC124\uBA85 \uBAA8\uB450 \uC6D0\uB798\uB300\uB85C", "
|
|
1797
|
+
}, children: t("\uC124\uBA85 \uBAA8\uB450 \uC6D0\uB798\uB300\uB85C", "Reset all descriptions", "\u5168\u90E8\u6062\u590D\u539F\u59CB\u63CF\u8FF0") })
|
|
1680
1798
|
] });
|
|
1681
1799
|
} })
|
|
1682
1800
|
] }),
|
|
@@ -1685,7 +1803,7 @@ function PromptToolsPrototype({ locale, prompt, onPromptChange, provided, onProv
|
|
|
1685
1803
|
{
|
|
1686
1804
|
wide: true,
|
|
1687
1805
|
open: previewOpen,
|
|
1688
|
-
title: t("\uD504\uB86C\uD504\uD2B8 \uBBF8\uB9AC\uBCF4\uAE30", "Prompt
|
|
1806
|
+
title: t("\uD504\uB86C\uD504\uD2B8 \uBBF8\uB9AC\uBCF4\uAE30", "Prompt preview", "\u63D0\u793A\u8BCD\u7ED3\u679C\u9884\u89C8"),
|
|
1689
1807
|
closeLabel: t("\uB2EB\uAE30", "Close preview", "\u5173\u95ED\u9884\u89C8"),
|
|
1690
1808
|
onClose: closePreview,
|
|
1691
1809
|
subtitle: result ? t(`\uC139\uC158 ${result.sections.length}\uAC1C \xB7 \uB3C4\uAD6C ${result.tools.length}\uAC1C`, `${result.sections.length} sections \xB7 ${result.tools.length} tools`, `${result.sections.length} \u4E2A\u7AE0\u8282 \xB7 ${result.tools.length} \u4E2A\u5DE5\u5177`) : void 0,
|
|
@@ -1744,7 +1862,7 @@ function parameterFields(schema, prefix = "") {
|
|
|
1744
1862
|
// src/detail-layout.tsx
|
|
1745
1863
|
var import_react8 = __toESM(require("react"), 1);
|
|
1746
1864
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1747
|
-
function DetailLayout({ title, subtitle, navigation, pages, selected, onSelect }) {
|
|
1865
|
+
function DetailLayout({ title, subtitle, navigation, pages, selected, onSelect, footer }) {
|
|
1748
1866
|
const id = import_react8.default.useId();
|
|
1749
1867
|
const scroller = import_react8.default.useRef(null);
|
|
1750
1868
|
import_react8.default.useLayoutEffect(() => {
|
|
@@ -1769,7 +1887,8 @@ function DetailLayout({ title, subtitle, navigation, pages, selected, onSelect }
|
|
|
1769
1887
|
children: page.label
|
|
1770
1888
|
}
|
|
1771
1889
|
)
|
|
1772
|
-
] }, page.id))
|
|
1890
|
+
] }, page.id)),
|
|
1891
|
+
footer
|
|
1773
1892
|
] }),
|
|
1774
1893
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "studio-scroller", ref: scroller, "data-studio-scroller": "", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "studio-content", children: pages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1775
1894
|
"section",
|
|
@@ -1786,13 +1905,17 @@ function DetailLayout({ title, subtitle, navigation, pages, selected, onSelect }
|
|
|
1786
1905
|
|
|
1787
1906
|
// src/optimization-prototype.tsx
|
|
1788
1907
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1908
|
+
var withoutSubagentFilter = (request) => {
|
|
1909
|
+
const { subagentToolFilter: _filter, ...rest } = request;
|
|
1910
|
+
return rest;
|
|
1911
|
+
};
|
|
1789
1912
|
var initial = { prompt: "Report evidence, uncertainty and remaining work.", tools: "read / grep / glob", spill: "2048", wait: "60000" };
|
|
1790
1913
|
var seeds = [
|
|
1791
1914
|
{ name: "Researcher", role: "research", model: "inherit", reasoning: "inherit", spawn: "fresh", persona: "Investigate primary sources and cite the evidence." },
|
|
1792
1915
|
{ name: "Reviewer", role: "review", model: "inherit", reasoning: "inherit", spawn: "fork", persona: "Review correctness and identify concrete risks." }
|
|
1793
1916
|
];
|
|
1794
|
-
function OptimizationPrototype({ locale, catalog, catalogError, onPreview, presetActions, extensionActions }) {
|
|
1795
|
-
const t = (
|
|
1917
|
+
function OptimizationPrototype({ locale, catalog, catalogError, onPreview, presetActions, extensionActions, navFooter }) {
|
|
1918
|
+
const t = (ko3, en3, zh3) => locale.startsWith("ko") ? ko3 : locale.startsWith("zh") ? zh3 : en3;
|
|
1796
1919
|
const [page, setPage] = import_react9.default.useState("list");
|
|
1797
1920
|
const [common, setCommon] = import_react9.default.useState({ ...initial });
|
|
1798
1921
|
const [agents, setAgents] = import_react9.default.useState(() => seeds.map((a) => ({ ...a })));
|
|
@@ -1807,6 +1930,8 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1807
1930
|
const [configDraft, setConfigDraft] = import_react9.default.useState();
|
|
1808
1931
|
const configOverrides = configDraft ?? defaults;
|
|
1809
1932
|
const [request, setRequest] = import_react9.default.useState();
|
|
1933
|
+
const [hiddenFromSubagents, setHiddenFromSubagents] = import_react9.default.useState([]);
|
|
1934
|
+
const selectable = (names2) => names2.filter((name2) => provided.includes(name2) && name2 !== ROLE_TOOL);
|
|
1810
1935
|
const [saving, setSaving] = import_react9.default.useState(false);
|
|
1811
1936
|
const [saveError, setSaveError] = import_react9.default.useState("");
|
|
1812
1937
|
const save = async () => {
|
|
@@ -1814,7 +1939,7 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1814
1939
|
setSaving(true);
|
|
1815
1940
|
setSaveError("");
|
|
1816
1941
|
try {
|
|
1817
|
-
await presetActions.save(JSON.stringify({ ...editing?.id ? { id: editing.id } : {}, name: name.trim(), description, request: { ...request, configOverrides }, conveniences: { spill: common.spill }, agents }));
|
|
1942
|
+
await presetActions.save(JSON.stringify({ ...editing?.id ? { id: editing.id } : {}, name: name.trim(), description, request: { ...withoutSubagentFilter(request), configOverrides, ...selectable(hiddenFromSubagents).length ? { subagentToolFilter: { deny: selectable(hiddenFromSubagents) } } : {} }, conveniences: { spill: common.spill }, agents: agents.map((role) => role.toolFilter ? { ...role, toolFilter: { ...role.toolFilter, deny: selectable(role.toolFilter.deny) } } : role) }));
|
|
1818
1943
|
setRevision((n) => n + 1);
|
|
1819
1944
|
setPage("list");
|
|
1820
1945
|
setName("");
|
|
@@ -1823,6 +1948,7 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1823
1948
|
setCommon({ ...initial });
|
|
1824
1949
|
setProvided([]);
|
|
1825
1950
|
setAgents(seeds.map((a) => ({ ...a })));
|
|
1951
|
+
setHiddenFromSubagents([]);
|
|
1826
1952
|
setEditing(void 0);
|
|
1827
1953
|
setTab("tools");
|
|
1828
1954
|
setDraftKey((n) => n + 1);
|
|
@@ -1832,15 +1958,16 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1832
1958
|
setSaving(false);
|
|
1833
1959
|
}
|
|
1834
1960
|
};
|
|
1835
|
-
const editPreset = (item,
|
|
1836
|
-
setEditing(
|
|
1837
|
-
setName(
|
|
1961
|
+
const editPreset = (item, copy3 = false) => {
|
|
1962
|
+
setEditing(copy3 ? { ...item, id: "" } : item);
|
|
1963
|
+
setName(copy3 ? `${item.name} Copy` : item.name);
|
|
1838
1964
|
setDescription(item.description);
|
|
1839
1965
|
setCommon({ ...initial, prompt: item.request.prompt, spill: item.conveniences?.spill ?? initial.spill });
|
|
1840
1966
|
setProvided([...item.request.tools]);
|
|
1841
1967
|
setConfigDraft(item.request.configOverrides ?? {});
|
|
1842
1968
|
setAgents(item.agents.map((role) => ({ ...role })));
|
|
1843
1969
|
setRequest(item.request);
|
|
1970
|
+
setHiddenFromSubagents([...item.request.subagentToolFilter?.deny ?? []]);
|
|
1844
1971
|
setDraftKey((n) => n + 1);
|
|
1845
1972
|
setPage("create");
|
|
1846
1973
|
};
|
|
@@ -1848,7 +1975,9 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1848
1975
|
const presetPersona = request?.providerConfigs?.[persona]?.prefix;
|
|
1849
1976
|
const masterPersona = catalog?.presets?.find((p) => p.id === (request?.preset ?? "studio-master"))?.promptProviders?.find((p) => p.name === persona)?.fields?.find((f) => f.key === "prefix")?.value;
|
|
1850
1977
|
const defaultPersona = typeof presetPersona === "string" ? presetPersona : typeof masterPersona === "string" ? masterPersona : "";
|
|
1851
|
-
const
|
|
1978
|
+
const toolChoices = (catalog?.tools ?? []).filter((tool) => provided.includes(tool.name) && tool.name !== ROLE_TOOL).map((tool) => ({ name: tool.name, description: tool.description }));
|
|
1979
|
+
const delegates = provided.some((name2) => name2 === ROLE_TOOL || GENERIC_DELEGATION_TOOLS.includes(name2));
|
|
1980
|
+
const agentPage = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(RoleEditor, { locale, roles: agents, onChange: setAgents, loadModels: presetActions?.models, defaultPersona, tools: toolChoices, hiddenTools: hiddenFromSubagents, onHiddenToolsChange: setHiddenFromSubagents, delegates }, draftKey);
|
|
1852
1981
|
const tabs = [
|
|
1853
1982
|
{ id: "tools", label: t("\uD504\uB86C\uD504\uD2B8\xB7\uB3C4\uAD6C", "Prompts & tools", "\u63D0\u793A\u8BCD\u4E0E\u5DE5\u5177"), content: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PromptToolsPrototype, { initialRequest: editing?.request, locale, catalog, catalogError, onPreview: onPreview ? (request2) => onPreview({ ...request2, configOverrides }) : void 0, onRequestChange: setRequest, prompt: common.prompt, onPromptChange: (value) => setCommon((c) => ({ ...c, prompt: value })), provided, onProvidedChange: setProvided }, draftKey) },
|
|
1854
1983
|
{ id: "convenience", label: t("\uC2E4\uD589 \uC124\uC815", "Execution settings", "\u6267\u884C\u8BBE\u7F6E"), content: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
@@ -1858,7 +1987,7 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1858
1987
|
{ id: "agents", label: t("\uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8", "Subagent settings", "\u5B50\u4EE3\u7406\u8BBE\u7F6E"), content: agentPage }
|
|
1859
1988
|
];
|
|
1860
1989
|
const tabId = import_react9.default.useId();
|
|
1861
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DetailLayout, { title: "DSH Studio", subtitle: t("\uC5D0\uC774\uC804\uD2B8 \uD504\uB9AC\uC14B \uD3B8\uC9D1\uAE30", "Agent preset editor", "\u4EE3\u7406\u9884\u8BBE\u7F16\u8F91\u5668"), navigation: t("Studio \uBA54\uB274", "
|
|
1990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DetailLayout, { footer: navFooter, title: "DSH Studio", subtitle: t("\uC5D0\uC774\uC804\uD2B8 \uD504\uB9AC\uC14B \uD3B8\uC9D1\uAE30", "Agent preset editor", "\u4EE3\u7406\u9884\u8BBE\u7F16\u8F91\u5668"), navigation: t("Studio \uBA54\uB274", "Studio menu", "\u9884\u8BBE\u5BFC\u822A"), selected: page, onSelect: (next) => {
|
|
1862
1991
|
if (next === "create" && editing) {
|
|
1863
1992
|
setEditing(void 0);
|
|
1864
1993
|
setName("");
|
|
@@ -1873,7 +2002,7 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1873
2002
|
}, pages: [
|
|
1874
2003
|
{ id: "list", group: t("\uD504\uB9AC\uC14B", "Presets", "\u9884\u8BBE"), label: t("\uD504\uB9AC\uC14B \uBAA9\uB85D", "Preset list", "\u9884\u8BBE\u5217\u8868"), content: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PresetList, { locale, api: presetActions, revision, onEdit: (item) => editPreset(item), onCopy: (item) => editPreset(item, true) }) },
|
|
1875
2004
|
{ id: "create", group: t("\uD504\uB9AC\uC14B", "Presets", "\u9884\u8BBE"), label: editing ? t("\uD504\uB9AC\uC14B \uD3B8\uC9D1", "Edit preset", "\u7F16\u8F91\u9884\u8BBE") : t("\uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30", "Create preset", "\u521B\u5EFA\u9884\u8BBE"), content: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "studio-page-stack", children: [
|
|
1876
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PageHead, { title: editing ? t("\uD504\uB9AC\uC14B \uD3B8\uC9D1", "Edit preset", "\u7F16\u8F91\u9884\u8BBE") : t("\uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30", "Create preset", "\u521B\u5EFA\u9884\u8BBE"), description: editing ? t("\uC800\uC7A5\
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PageHead, { title: editing ? t("\uD504\uB9AC\uC14B \uD3B8\uC9D1", "Edit preset", "\u7F16\u8F91\u9884\u8BBE") : t("\uD504\uB9AC\uC14B \uB9CC\uB4E4\uAE30", "Create preset", "\u521B\u5EFA\u9884\u8BBE"), description: editing ? t("\uC800\uC7A5 \uD6C4 \uC0C8 \uC138\uC158\uC5D0 \uC801\uC6A9\uD558\uB824\uBA74 \uD504\uB9AC\uC14B \uBAA9\uB85D\uC5D0\uC11C DSH\uC5D0 \uBC18\uC601\uD574 \uC8FC\uC138\uC694. \uC774\uBBF8 \uC2E4\uD589 \uC911\uC778 \uC138\uC158\uC5D0\uB294 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.", "After saving, apply to DSH from the preset list to use these settings in new sessions. Changes do not affect sessions that are already running.", "\u4FDD\u5B58\u540E\uFF0C\u8BF7\u5728\u9884\u8BBE\u5217\u8868\u4E2D\u5E94\u7528\u5230 DSH\uFF0C\u4EE5\u4FBF\u5728\u65B0\u4F1A\u8BDD\u4E2D\u4F7F\u7528\u8FD9\u4E9B\u8BBE\u7F6E\u3002\u66F4\u6539\u4E0D\u4F1A\u5F71\u54CD\u6B63\u5728\u8FD0\u884C\u7684\u4F1A\u8BDD\u3002") : t("\uD504\uB86C\uD504\uD2B8, \uB3C4\uAD6C, \uC2E4\uD589 \uC124\uC815, \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uB97C \uAD6C\uC131\uD574 \uC0C8 \uD504\uB9AC\uC14B\uC73C\uB85C \uC800\uC7A5\uD569\uB2C8\uB2E4.", "Configure prompts, tools, execution settings and subagents, then save a new preset.", "\u914D\u7F6E\u5DE5\u5177\u3001\u6267\u884C\u8BBE\u7F6E\u548C\u5B50\u4EE3\u7406\u89D2\u8272\uFF0C\u5E76\u4FDD\u5B58\u4E3A\u65B0\u9884\u8BBE"), actions: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { primary: true, disabled: saving || !presetActions || !request || !name.trim(), onClick: () => void save(), children: saving ? t("\uC800\uC7A5 \uC911\u2026", "Saving\u2026", "\u4FDD\u5B58\u4E2D\u2026") : t("\uD504\uB9AC\uC14B \uC800\uC7A5", "Save preset", "\u4FDD\u5B58\u9884\u8BBE") }) }),
|
|
1877
2006
|
saveError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Notice, { children: t(`\uD504\uB9AC\uC14B\uC744 \uC800\uC7A5\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uD3B8\uC9D1\uD55C \uB0B4\uC6A9\uC740 \uD654\uBA74\uC5D0 \uADF8\uB300\uB85C \uC788\uC2B5\uB2C8\uB2E4. (${saveError})`, `Could not save the preset. Your edits remain on this screen. (${saveError})`, `\u65E0\u6CD5\u4FDD\u5B58\u9884\u8BBE\uFF0C\u7F16\u8F91\u5185\u5BB9\u4ECD\u4FDD\u7559\u5728\u6B64\u9875\u9762\uFF08${saveError}\uFF09`) }),
|
|
1878
2007
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "studio-identity", children: [
|
|
1879
2008
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "studio-field studio-identity-name", children: [
|
|
@@ -1899,7 +2028,7 @@ function OptimizationPrototype({ locale, catalog, catalogError, onPreview, prese
|
|
|
1899
2028
|
}
|
|
1900
2029
|
|
|
1901
2030
|
// src/shell.tsx
|
|
1902
|
-
var
|
|
2031
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
1903
2032
|
var import_dsh_client_ui_slots = require("@deepseek-ai/dsh-client-ui-slots");
|
|
1904
2033
|
|
|
1905
2034
|
// src/service-layout.tsx
|
|
@@ -1943,8 +2072,145 @@ function ServiceLayout({ locale, services, renderSlot }) {
|
|
|
1943
2072
|
] });
|
|
1944
2073
|
}
|
|
1945
2074
|
|
|
1946
|
-
// src/
|
|
2075
|
+
// src/update-store.ts
|
|
2076
|
+
function createUpdateStore(actions, current) {
|
|
2077
|
+
let state = { phase: "idle", current };
|
|
2078
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2079
|
+
const set = (next) => {
|
|
2080
|
+
state = next;
|
|
2081
|
+
listeners.forEach((listener) => listener());
|
|
2082
|
+
};
|
|
2083
|
+
return {
|
|
2084
|
+
getSnapshot: () => state,
|
|
2085
|
+
subscribe(listener) {
|
|
2086
|
+
listeners.add(listener);
|
|
2087
|
+
return () => {
|
|
2088
|
+
listeners.delete(listener);
|
|
2089
|
+
};
|
|
2090
|
+
},
|
|
2091
|
+
async refresh(force = false) {
|
|
2092
|
+
if (state.phase === "updating" || state.phase === "installed") return;
|
|
2093
|
+
try {
|
|
2094
|
+
const status = await actions.status(force);
|
|
2095
|
+
const phase = () => state.phase;
|
|
2096
|
+
if (phase() === "updating" || phase() === "installed") return;
|
|
2097
|
+
if (status.installed) {
|
|
2098
|
+
set({ phase: "installed", current: status.current, version: status.installed });
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
const version = status.available && !status.blocked ? status.available : void 0;
|
|
2102
|
+
set({ phase: "idle", current: status.current, ...version ? { version } : {} });
|
|
2103
|
+
} catch {
|
|
2104
|
+
}
|
|
2105
|
+
},
|
|
2106
|
+
async update() {
|
|
2107
|
+
if (state.phase !== "idle" && state.phase !== "failed") return;
|
|
2108
|
+
const version = state.version;
|
|
2109
|
+
if (!version) return;
|
|
2110
|
+
set({ phase: "updating", current: state.current, version });
|
|
2111
|
+
try {
|
|
2112
|
+
const result = await actions.update(version);
|
|
2113
|
+
if (result.status === "restart-required" || result.status === "applied") set({ phase: "installed", current: state.current, version: result.version });
|
|
2114
|
+
else set({ phase: "failed", current: state.current, version, message: result.message ?? result.status });
|
|
2115
|
+
} catch (error) {
|
|
2116
|
+
set({ phase: "failed", current: state.current, version, message: error instanceof Error ? error.message : String(error) });
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
// src/update-indicator.tsx
|
|
2123
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
2124
|
+
var import_react_dom = require("react-dom");
|
|
1947
2125
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2126
|
+
var ko2 = {
|
|
2127
|
+
available: (v) => `v${v}\uB85C \uC5C5\uB370\uC774\uD2B8`,
|
|
2128
|
+
updating: (v) => `v${v} \uC124\uCE58 \uC911`,
|
|
2129
|
+
installed: (v) => `v${v}\uB97C \uC124\uCE58\uD588\uC2B5\uB2C8\uB2E4. DSH\uB97C \uB2E4\uC2DC \uC2DC\uC791\uD558\uBA74 \uC801\uC6A9\uB429\uB2C8\uB2E4.`,
|
|
2130
|
+
failed: (v, message2) => `v${v}\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uB824\uBA74 \uB204\uB974\uC138\uC694. (${message2})`
|
|
2131
|
+
};
|
|
2132
|
+
var en2 = {
|
|
2133
|
+
available: (v) => `Update to v${v}`,
|
|
2134
|
+
updating: (v) => `Installing v${v}`,
|
|
2135
|
+
installed: (v) => `Installed v${v}. Restart DSH to use it.`,
|
|
2136
|
+
failed: (v, message2) => `Could not update to v${v}. Select to try again. (${message2})`
|
|
2137
|
+
};
|
|
2138
|
+
var zh2 = {
|
|
2139
|
+
available: (v) => `\u66F4\u65B0\u5230 v${v}`,
|
|
2140
|
+
updating: (v) => `\u6B63\u5728\u5B89\u88C5 v${v}`,
|
|
2141
|
+
installed: (v) => `\u5DF2\u5B89\u88C5 v${v}\u3002\u91CD\u542F DSH \u540E\u751F\u6548`,
|
|
2142
|
+
failed: (v, message2) => `\u65E0\u6CD5\u66F4\u65B0\u5230 v${v}\u3002\u70B9\u51FB\u91CD\u8BD5\uFF08${message2}\uFF09`
|
|
2143
|
+
};
|
|
2144
|
+
var copy2 = (locale) => locale.startsWith("ko") ? ko2 : locale.startsWith("zh") ? zh2 : en2;
|
|
2145
|
+
function useUpdateState(store) {
|
|
2146
|
+
return import_react11.default.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
2147
|
+
}
|
|
2148
|
+
function updateLabel(state, locale) {
|
|
2149
|
+
const t = copy2(locale);
|
|
2150
|
+
if (state.phase === "updating") return t.updating(state.version);
|
|
2151
|
+
if (state.phase === "installed") return t.installed(state.version);
|
|
2152
|
+
if (state.phase === "failed") return t.failed(state.version, state.message);
|
|
2153
|
+
return state.version ? t.available(state.version) : void 0;
|
|
2154
|
+
}
|
|
2155
|
+
function UpdateGlyph({ phase, size = 14 }) {
|
|
2156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
2157
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "8", cy: "8", r: "6.5" }),
|
|
2158
|
+
phase === "installed" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M5.2 8.2l1.9 1.9 3.7-4" }) : phase === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M8 4.8v3.8M8 11.2v.01" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M8 11V5.2M5.4 7.6L8 5l2.6 2.6" })
|
|
2159
|
+
] });
|
|
2160
|
+
}
|
|
2161
|
+
function VersionFooter({ store, locale }) {
|
|
2162
|
+
const state = useUpdateState(store);
|
|
2163
|
+
const label = updateLabel(state, locale);
|
|
2164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "studio-nav-footer", children: [
|
|
2165
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "studio-mono", children: [
|
|
2166
|
+
"v",
|
|
2167
|
+
state.current
|
|
2168
|
+
] }),
|
|
2169
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2170
|
+
IconButton,
|
|
2171
|
+
{
|
|
2172
|
+
label,
|
|
2173
|
+
tone: state.phase === "failed" ? "error" : state.phase === "installed" ? "success" : "info",
|
|
2174
|
+
disabled: state.phase === "updating" || state.phase === "installed",
|
|
2175
|
+
busy: state.phase === "updating",
|
|
2176
|
+
onClick: () => {
|
|
2177
|
+
void store.update();
|
|
2178
|
+
},
|
|
2179
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(UpdateGlyph, { phase: state.phase })
|
|
2180
|
+
}
|
|
2181
|
+
)
|
|
2182
|
+
] });
|
|
2183
|
+
}
|
|
2184
|
+
function SidebarIcon({ size = 20, store, locale }) {
|
|
2185
|
+
const state = useUpdateState(store);
|
|
2186
|
+
const label = updateLabel(state, locale);
|
|
2187
|
+
const glyph = import_react11.default.useRef(null);
|
|
2188
|
+
const [row, setRow] = import_react11.default.useState(null);
|
|
2189
|
+
import_react11.default.useLayoutEffect(() => {
|
|
2190
|
+
setRow(glyph.current?.closest("button") ?? null);
|
|
2191
|
+
}, [size]);
|
|
2192
|
+
const wide = size <= 16;
|
|
2193
|
+
const marked = label !== void 0 && state.phase !== "installed";
|
|
2194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "studio-ui studio-sidebar-glyph", children: [
|
|
2196
|
+
marked && !wide && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: sidebarMarkStyles }),
|
|
2197
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { ref: glyph, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.7", "aria-hidden": "true", children: [
|
|
2198
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "3", y: "3", width: "7", height: "7", rx: "2" }),
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "14", y: "3", width: "7", height: "7", rx: "2" }),
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "3", y: "14", width: "7", height: "7", rx: "2" }),
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M17.5 14v7M14 17.5h7" }),
|
|
2202
|
+
marked && !wide && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { className: "studio-sidebar-dot", cx: "21", cy: "3", r: "3", stroke: "none" })
|
|
2203
|
+
] })
|
|
2204
|
+
] }),
|
|
2205
|
+
marked && wide && row && (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "studio-ui studio-sidebar-update", "data-phase": state.phase, title: label, role: "img", "aria-label": label, children: [
|
|
2206
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: sidebarMarkStyles }),
|
|
2207
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(UpdateGlyph, { phase: state.phase, size: 14 })
|
|
2208
|
+
] }), row)
|
|
2209
|
+
] });
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
// src/shell.tsx
|
|
2213
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1948
2214
|
var inject = ["slots", "locale", "remote"];
|
|
1949
2215
|
var panel = "local-dsh-studio";
|
|
1950
2216
|
async function apply(ctx) {
|
|
@@ -1965,7 +2231,18 @@ async function apply(ctx) {
|
|
|
1965
2231
|
invocation: { kind: "direct" },
|
|
1966
2232
|
parameters: [{ name: "request", wire: "request", source: "json", codec: { mode: "strict", typeSymbol: "PreviewRequest", create: () => ({ parse: parsePreviewRequest }) } }],
|
|
1967
2233
|
result: { mode: "src-json" }
|
|
1968
|
-
}, ...["
|
|
2234
|
+
}, ...["updateStatus", "updateStudio"].map((method) => ({
|
|
2235
|
+
id: `${PACKAGE_NAME}#studioCatalog/${method}`,
|
|
2236
|
+
service: "studioCatalog",
|
|
2237
|
+
namespace: "studioCatalog",
|
|
2238
|
+
method,
|
|
2239
|
+
invocation: { kind: "direct" },
|
|
2240
|
+
parameters: [{ name: method === "updateStatus" ? "force" : "version", wire: method === "updateStatus" ? "force" : "version", source: "json", codec: { mode: "strict", typeSymbol: "string", create: () => ({ parse: (value) => {
|
|
2241
|
+
if (typeof value !== "string") throw new TypeError("Expected a string");
|
|
2242
|
+
return value;
|
|
2243
|
+
} }) } }],
|
|
2244
|
+
result: { mode: "src-json" }
|
|
2245
|
+
})), ...["listPresets", "savePreset", "applyPreset", "unapplyPreset", "roleModels", "deletePreset", "readExtensions", "saveExtensions"].map((method) => ({
|
|
1969
2246
|
id: `${PACKAGE_NAME}#studioCatalog/${method}`,
|
|
1970
2247
|
service: "studioCatalog",
|
|
1971
2248
|
namespace: "studioCatalog",
|
|
@@ -1989,35 +2266,35 @@ async function apply(ctx) {
|
|
|
1989
2266
|
};
|
|
1990
2267
|
ctx.effect(() => ctx.slots.subscribe("local.dsh-studio.services", syncServices));
|
|
1991
2268
|
ctx.effect(() => ctx.locale.subscribe(syncServices));
|
|
2269
|
+
const updateActions = /* @__PURE__ */ (() => {
|
|
2270
|
+
const call = async (method, arg) => {
|
|
2271
|
+
const service = ctx.get("remote.studioCatalog");
|
|
2272
|
+
const fn = service?.[method];
|
|
2273
|
+
if (!fn) throw new Error("Studio update API unavailable");
|
|
2274
|
+
const result = await fn(arg);
|
|
2275
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Update request failed");
|
|
2276
|
+
return result.value;
|
|
2277
|
+
};
|
|
2278
|
+
return {
|
|
2279
|
+
status: (force) => call("updateStatus", force ? "force" : ""),
|
|
2280
|
+
update: (version) => call("updateStudio", version)
|
|
2281
|
+
};
|
|
2282
|
+
})();
|
|
2283
|
+
const updates = createUpdateStore(updateActions, STUDIO_VERSION);
|
|
2284
|
+
void updates.refresh();
|
|
1992
2285
|
function StudioServices({ renderSlot }) {
|
|
1993
|
-
const items =
|
|
2286
|
+
const items = import_react12.default.useSyncExternalStore((listener) => {
|
|
1994
2287
|
serviceListeners.add(listener);
|
|
1995
2288
|
return () => {
|
|
1996
2289
|
serviceListeners.delete(listener);
|
|
1997
2290
|
};
|
|
1998
2291
|
}, () => services);
|
|
1999
|
-
const locale =
|
|
2000
|
-
return /* @__PURE__ */ (0,
|
|
2292
|
+
const locale = import_react12.default.useSyncExternalStore((listener) => ctx.locale.subscribe(listener), () => ctx.locale.getLocale().active);
|
|
2293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(StudioSurface, { className: "studio-shell", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("main", { className: "studio-page", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ServiceLayout, { locale, services: items, renderSlot }) }) });
|
|
2001
2294
|
}
|
|
2002
2295
|
function Icon({ size = 20 }) {
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
{
|
|
2006
|
-
width: size,
|
|
2007
|
-
height: size,
|
|
2008
|
-
viewBox: "0 0 24 24",
|
|
2009
|
-
fill: "none",
|
|
2010
|
-
stroke: "currentColor",
|
|
2011
|
-
strokeWidth: "1.7",
|
|
2012
|
-
"aria-hidden": "true",
|
|
2013
|
-
children: [
|
|
2014
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "3", y: "3", width: "7", height: "7", rx: "2" }),
|
|
2015
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "14", y: "3", width: "7", height: "7", rx: "2" }),
|
|
2016
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "3", y: "14", width: "7", height: "7", rx: "2" }),
|
|
2017
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M17.5 14v7M14 17.5h7" })
|
|
2018
|
-
]
|
|
2019
|
-
}
|
|
2020
|
-
);
|
|
2296
|
+
const locale = import_react12.default.useSyncExternalStore((listener) => ctx.locale.subscribe(listener), () => ctx.locale.getLocale().active);
|
|
2297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SidebarIcon, { size, store: updates, locale });
|
|
2021
2298
|
}
|
|
2022
2299
|
ctx.slots.inject(
|
|
2023
2300
|
"main",
|
|
@@ -2033,10 +2310,10 @@ async function apply(ctx) {
|
|
|
2033
2310
|
)
|
|
2034
2311
|
);
|
|
2035
2312
|
function OptimizationPage() {
|
|
2036
|
-
const locale =
|
|
2037
|
-
const [catalog, setCatalog] =
|
|
2038
|
-
const [catalogError, setCatalogError] =
|
|
2039
|
-
|
|
2313
|
+
const locale = import_react12.default.useSyncExternalStore((listener) => ctx.locale.subscribe(listener), () => ctx.locale.getLocale().active);
|
|
2314
|
+
const [catalog, setCatalog] = import_react12.default.useState();
|
|
2315
|
+
const [catalogError, setCatalogError] = import_react12.default.useState("");
|
|
2316
|
+
import_react12.default.useEffect(() => {
|
|
2040
2317
|
let active = true;
|
|
2041
2318
|
const remote2 = ctx.get("remote.studioCatalog");
|
|
2042
2319
|
if (!remote2) {
|
|
@@ -2054,7 +2331,7 @@ async function apply(ctx) {
|
|
|
2054
2331
|
active = false;
|
|
2055
2332
|
};
|
|
2056
2333
|
}, []);
|
|
2057
|
-
const presetActions =
|
|
2334
|
+
const presetActions = import_react12.default.useMemo(() => {
|
|
2058
2335
|
const call = async (method, ...args) => {
|
|
2059
2336
|
const service = ctx.get("remote.studioCatalog");
|
|
2060
2337
|
const result = await service[method](...args);
|
|
@@ -2070,7 +2347,7 @@ async function apply(ctx) {
|
|
|
2070
2347
|
delete: (id) => call("deletePreset", id)
|
|
2071
2348
|
};
|
|
2072
2349
|
}, []);
|
|
2073
|
-
const extensionActions =
|
|
2350
|
+
const extensionActions = import_react12.default.useMemo(() => {
|
|
2074
2351
|
const call = async (method, ...args) => {
|
|
2075
2352
|
const service = ctx.get("remote.studioCatalog");
|
|
2076
2353
|
const result = await service[method](...args);
|
|
@@ -2081,7 +2358,10 @@ async function apply(ctx) {
|
|
|
2081
2358
|
setCatalog(await call("saveExtensions", payload));
|
|
2082
2359
|
} };
|
|
2083
2360
|
}, []);
|
|
2084
|
-
|
|
2361
|
+
import_react12.default.useEffect(() => {
|
|
2362
|
+
void updates.refresh();
|
|
2363
|
+
}, []);
|
|
2364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OptimizationPrototype, { navFooter: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(VersionFooter, { store: updates, locale }), extensionActions, presetActions, locale, catalog, catalogError, onPreview: async (request) => {
|
|
2085
2365
|
const service = ctx.get("remote.studioCatalog");
|
|
2086
2366
|
const response = await service.preview(request);
|
|
2087
2367
|
if (!response.ok) throw new Error(response.error?.message ?? "Preview failed");
|