@deepseek-ai/dsh-client-ui-settings-plugins 0.1.6-alpha.2 → 0.1.7-alpha.1
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.i18n.yaml +2 -2
- package/README.md +11 -46
- package/README.zh.md +15 -50
- package/lib/client.js +15 -1753
- package/lib/types/client/index.d.ts +6 -14
- package/lib/types/client/locales.d.ts +3 -3
- package/package.json +11 -16
- package/lib/types/client/AgentLoopCard.d.ts +0 -12
- package/lib/types/client/BashCard.d.ts +0 -12
- package/lib/types/client/PluginConfigForm.d.ts +0 -34
- package/lib/types/client/SubagentCard.d.ts +0 -12
- package/lib/types/client/SubagentLimitsFields.d.ts +0 -14
- package/lib/types/client/SubagentModelSelectionFields.d.ts +0 -14
- package/lib/types/client/WebSearchCard.d.ts +0 -16
- package/lib/types/client/agent-loop-card-controller.d.ts +0 -43
- package/lib/types/client/bash-card-controller.d.ts +0 -45
- package/lib/types/client/card-form.d.ts +0 -171
- package/lib/types/client/fields.d.ts +0 -69
- package/lib/types/client/subagent-card-controller.d.ts +0 -32
- package/lib/types/client/subagent-limits-card-controller.d.ts +0 -33
- package/lib/types/client/subagent-model-selection-card-controller.d.ts +0 -129
- package/lib/types/client/web-search-card-controller.d.ts +0 -93
package/lib/client.js
CHANGED
|
@@ -7,333 +7,14 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let _deepseek_ai_dsh_client_ui_slots = require("@deepseek-ai/dsh-client-ui-slots");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react = require("react");
|
|
10
|
-
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
11
|
-
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
12
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/fields.module.css.mjs
|
|
13
|
-
const css$5 = ".At1oFq_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.At1oFq_field+.At1oFq_field{border-top:.5px solid var(--dsw-alias-border-l2)}.At1oFq_head{align-items:center;gap:8px;display:flex}.At1oFq_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.At1oFq_labelGroup{flex:1;align-items:center;gap:4px;min-width:0;display:flex}.At1oFq_labelGroup>.At1oFq_label{flex:0 auto}.At1oFq_helpButton{width:24px;height:24px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.At1oFq_helpButton:hover,.At1oFq_helpButton[aria-expanded=true]{background:var(--dsw-alias-bg-layer-4);color:var(--dsw-alias-label-secondary)}.At1oFq_helpButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.At1oFq_help{color:var(--dsw-alias-label-secondary);padding:10px 0 0;font-size:12px;line-height:1.6}.At1oFq_help>p{margin:0}.At1oFq_help>p+p{margin-top:8px}.At1oFq_badges{align-items:center;gap:8px;display:inline-flex}.At1oFq_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.At1oFq_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.At1oFq_reset:disabled{cursor:default}.At1oFq_input{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.At1oFq_input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.At1oFq_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.At1oFq_input[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}.At1oFq_invalid{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:1.5}.At1oFq_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}";
|
|
14
|
-
const tagId$5 = "@deepseek-ai/dsh-client-ui-settings-plugins/fields.module.css";
|
|
15
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
|
|
16
|
-
const tag = document.createElement("style");
|
|
17
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
18
|
-
tag.dataset.pluginCss = tagId$5;
|
|
19
|
-
tag.textContent = css$5;
|
|
20
|
-
document.head.appendChild(tag);
|
|
21
|
-
}
|
|
22
|
-
var fields_module_css_default = {
|
|
23
|
-
"badges": "At1oFq_badges",
|
|
24
|
-
"field": "At1oFq_field",
|
|
25
|
-
"head": "At1oFq_head",
|
|
26
|
-
"help": "At1oFq_help",
|
|
27
|
-
"helpButton": "At1oFq_helpButton",
|
|
28
|
-
"hint": "At1oFq_hint",
|
|
29
|
-
"input": "At1oFq_input",
|
|
30
|
-
"invalid": "At1oFq_invalid",
|
|
31
|
-
"label": "At1oFq_label",
|
|
32
|
-
"labelGroup": "At1oFq_labelGroup",
|
|
33
|
-
"reset": "At1oFq_reset"
|
|
34
|
-
};
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region lib/types/client/fields.js
|
|
37
|
-
/**
|
|
38
|
-
* Hand-written controls for the plugin configuration forms. Each renders one
|
|
39
|
-
* field's label, its staged text, whether saving would leave an override, and
|
|
40
|
-
* — when one stands — the reset that stages a clear back to the composition
|
|
41
|
-
* layer. Nothing here writes: a control reports what the user typed, and the
|
|
42
|
-
* card's save is the single point where a draft becomes a document mutation.
|
|
43
|
-
*/
|
|
44
|
-
/**
|
|
45
|
-
* A staged value field. `numeric` only hints the keypad: which drafts a field
|
|
46
|
-
* accepts is decided by its spec, so the control never silently rewrites what
|
|
47
|
-
* the user typed.
|
|
48
|
-
* @param props - the field's copy, its staged text, and the edit actions.
|
|
49
|
-
* @returns the labelled control.
|
|
50
|
-
*/
|
|
51
|
-
function ValueField(props) {
|
|
52
|
-
const [helpOpen, setHelpOpen] = (0, react.useState)(false);
|
|
53
|
-
const helpId = `${props.id}-help`;
|
|
54
|
-
const messageId = `${props.id}-message`;
|
|
55
|
-
const hasMessage = props.invalid || Boolean(props.hint);
|
|
56
|
-
const description = [hasMessage ? messageId : "", helpOpen ? helpId : ""].filter(Boolean).join(" ");
|
|
57
|
-
return (0, react_jsx_runtime.jsxs)("div", {
|
|
58
|
-
className: fields_module_css_default.field,
|
|
59
|
-
children: [
|
|
60
|
-
(0, react_jsx_runtime.jsxs)("div", {
|
|
61
|
-
className: fields_module_css_default.head,
|
|
62
|
-
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
63
|
-
className: fields_module_css_default.labelGroup,
|
|
64
|
-
children: [(0, react_jsx_runtime.jsx)("label", {
|
|
65
|
-
className: fields_module_css_default.label,
|
|
66
|
-
htmlFor: props.id,
|
|
67
|
-
children: props.label
|
|
68
|
-
}), props.help !== void 0 ? (0, react_jsx_runtime.jsx)("button", {
|
|
69
|
-
type: "button",
|
|
70
|
-
className: fields_module_css_default.helpButton,
|
|
71
|
-
"aria-label": props.help.label,
|
|
72
|
-
"aria-expanded": helpOpen,
|
|
73
|
-
"aria-controls": helpId,
|
|
74
|
-
onClick: () => {
|
|
75
|
-
setHelpOpen(!helpOpen);
|
|
76
|
-
},
|
|
77
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInfoOutline14, { size: 12 })
|
|
78
|
-
}) : null]
|
|
79
|
-
}), props.overridden ? (0, react_jsx_runtime.jsxs)("span", {
|
|
80
|
-
className: fields_module_css_default.badges,
|
|
81
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
|
|
82
|
-
tone: "neutral",
|
|
83
|
-
children: props.overriddenLabel
|
|
84
|
-
}), (0, react_jsx_runtime.jsx)("button", {
|
|
85
|
-
type: "button",
|
|
86
|
-
className: fields_module_css_default.reset,
|
|
87
|
-
disabled: props.disabled,
|
|
88
|
-
onClick: props.onReset,
|
|
89
|
-
children: props.resetLabel
|
|
90
|
-
})]
|
|
91
|
-
}) : null]
|
|
92
|
-
}),
|
|
93
|
-
(0, react_jsx_runtime.jsx)("input", {
|
|
94
|
-
id: props.id,
|
|
95
|
-
className: fields_module_css_default.input,
|
|
96
|
-
type: "text",
|
|
97
|
-
...props.numeric === true ? { inputMode: "numeric" } : {},
|
|
98
|
-
...props.invalid ? { "aria-invalid": true } : {},
|
|
99
|
-
"aria-describedby": description || void 0,
|
|
100
|
-
value: props.text,
|
|
101
|
-
placeholder: props.placeholder ?? "",
|
|
102
|
-
disabled: props.disabled,
|
|
103
|
-
onChange: (event) => {
|
|
104
|
-
props.onEdit(event.target.value);
|
|
105
|
-
}
|
|
106
|
-
}),
|
|
107
|
-
hasMessage ? (0, react_jsx_runtime.jsx)("p", {
|
|
108
|
-
id: messageId,
|
|
109
|
-
className: props.invalid ? fields_module_css_default.invalid : fields_module_css_default.hint,
|
|
110
|
-
children: props.invalid ? props.invalidLabel : props.hint
|
|
111
|
-
}) : null,
|
|
112
|
-
props.help !== void 0 && helpOpen ? (0, react_jsx_runtime.jsx)("div", {
|
|
113
|
-
id: helpId,
|
|
114
|
-
className: fields_module_css_default.help,
|
|
115
|
-
role: "region",
|
|
116
|
-
"aria-label": props.help.label,
|
|
117
|
-
children: props.help.content
|
|
118
|
-
}) : null
|
|
119
|
-
]
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* A write-only credential control. The value never rides a response, so the
|
|
124
|
-
* control reports only whether one is configured and starts blank; a blank
|
|
125
|
-
* draft writes nothing, which keeps the stored key rather than clearing it.
|
|
126
|
-
* @param props - the field's copy, its staged text, and the configured state.
|
|
127
|
-
* @returns the labelled control.
|
|
128
|
-
*/
|
|
129
|
-
function SecretField(props) {
|
|
130
|
-
return (0, react_jsx_runtime.jsxs)("div", {
|
|
131
|
-
className: fields_module_css_default.field,
|
|
132
|
-
children: [
|
|
133
|
-
(0, react_jsx_runtime.jsxs)("div", {
|
|
134
|
-
className: fields_module_css_default.head,
|
|
135
|
-
children: [(0, react_jsx_runtime.jsx)("label", {
|
|
136
|
-
className: fields_module_css_default.label,
|
|
137
|
-
htmlFor: props.id,
|
|
138
|
-
children: props.label
|
|
139
|
-
}), (0, react_jsx_runtime.jsx)("span", {
|
|
140
|
-
className: fields_module_css_default.badges,
|
|
141
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
|
|
142
|
-
tone: props.configured ? "neutral" : "quiet",
|
|
143
|
-
children: props.stateLabel
|
|
144
|
-
})
|
|
145
|
-
})]
|
|
146
|
-
}),
|
|
147
|
-
(0, react_jsx_runtime.jsx)("input", {
|
|
148
|
-
id: props.id,
|
|
149
|
-
className: fields_module_css_default.input,
|
|
150
|
-
type: "password",
|
|
151
|
-
autoComplete: "off",
|
|
152
|
-
value: props.text,
|
|
153
|
-
disabled: props.disabled,
|
|
154
|
-
onChange: (event) => {
|
|
155
|
-
props.onEdit(event.target.value);
|
|
156
|
-
}
|
|
157
|
-
}),
|
|
158
|
-
(0, react_jsx_runtime.jsx)("p", {
|
|
159
|
-
className: fields_module_css_default.hint,
|
|
160
|
-
children: props.hint
|
|
161
|
-
})
|
|
162
|
-
]
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/PluginConfigForm.module.css.mjs
|
|
167
|
-
const css$4 = ".KQZgIq_form{flex-direction:column;display:flex}.KQZgIq_readOnly,.KQZgIq_unavailable{color:var(--dsw-alias-label-tertiary);margin:0 0 12px;font-size:12px;line-height:1.5}.KQZgIq_footer{align-items:center;gap:8px;padding-top:16px;display:flex}.KQZgIq_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.KQZgIq_save{appearance:none;font:inherit;cursor:pointer;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.KQZgIq_save:disabled{opacity:.4;cursor:default}.KQZgIq_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}";
|
|
168
|
-
const tagId$4 = "@deepseek-ai/dsh-client-ui-settings-plugins/PluginConfigForm.module.css";
|
|
169
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
170
|
-
const tag = document.createElement("style");
|
|
171
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
172
|
-
tag.dataset.pluginCss = tagId$4;
|
|
173
|
-
tag.textContent = css$4;
|
|
174
|
-
document.head.appendChild(tag);
|
|
175
|
-
}
|
|
176
|
-
var PluginConfigForm_module_css_default = {
|
|
177
|
-
"failed": "KQZgIq_failed",
|
|
178
|
-
"footer": "KQZgIq_footer",
|
|
179
|
-
"form": "KQZgIq_form",
|
|
180
|
-
"readOnly": "KQZgIq_readOnly",
|
|
181
|
-
"save": "KQZgIq_save",
|
|
182
|
-
"unavailable": "KQZgIq_unavailable"
|
|
183
|
-
};
|
|
184
|
-
//#endregion
|
|
185
|
-
//#region lib/types/client/PluginConfigForm.js
|
|
186
|
-
/**
|
|
187
|
-
* One plugin's configuration form as its page on the Plugins page shows it:
|
|
188
|
-
* the read-only notice when the deployment stores settings read-only, the
|
|
189
|
-
* plugin's controls, and the save that writes every staged edit. The page
|
|
190
|
-
* draws the plugin's title and one-liner itself.
|
|
191
|
-
*
|
|
192
|
-
* Only a save writes. Leaving the page drops every staged edit, so the form
|
|
193
|
-
* discards on unmount and offers no discard control. A form whose namespace
|
|
194
|
-
* the Host stopped serving says so in place of its controls rather than
|
|
195
|
-
* showing fields nothing would accept.
|
|
196
|
-
*/
|
|
197
|
-
/**
|
|
198
|
-
* Render one plugin's configuration form.
|
|
199
|
-
* @param props - the form state, its controls, and the save and discard actions.
|
|
200
|
-
* @returns the form, or the unavailable line while the namespace is not served.
|
|
201
|
-
*/
|
|
202
|
-
function PluginConfigForm(props) {
|
|
203
|
-
const { state } = props;
|
|
204
|
-
const discard = (0, react.useRef)(props.onDiscard);
|
|
205
|
-
discard.current = props.onDiscard;
|
|
206
|
-
(0, react.useEffect)(() => () => {
|
|
207
|
-
discard.current();
|
|
208
|
-
}, []);
|
|
209
|
-
if (!state.available) return (0, react_jsx_runtime.jsx)("p", {
|
|
210
|
-
className: PluginConfigForm_module_css_default.unavailable,
|
|
211
|
-
role: "status",
|
|
212
|
-
children: props.t("unavailable")
|
|
213
|
-
});
|
|
214
|
-
const blocked = !state.dirty || state.invalid || state.saving;
|
|
215
|
-
return (0, react_jsx_runtime.jsxs)("div", {
|
|
216
|
-
className: PluginConfigForm_module_css_default.form,
|
|
217
|
-
children: [
|
|
218
|
-
!state.writable ? (0, react_jsx_runtime.jsx)("p", {
|
|
219
|
-
className: PluginConfigForm_module_css_default.readOnly,
|
|
220
|
-
role: "status",
|
|
221
|
-
children: props.t("readOnly")
|
|
222
|
-
}) : null,
|
|
223
|
-
props.children,
|
|
224
|
-
(0, react_jsx_runtime.jsxs)("div", {
|
|
225
|
-
className: PluginConfigForm_module_css_default.footer,
|
|
226
|
-
children: [state.failed ? (0, react_jsx_runtime.jsx)("p", {
|
|
227
|
-
className: PluginConfigForm_module_css_default.failed,
|
|
228
|
-
role: "status",
|
|
229
|
-
children: props.t("saveFailed")
|
|
230
|
-
}) : null, (0, react_jsx_runtime.jsx)("button", {
|
|
231
|
-
type: "button",
|
|
232
|
-
className: PluginConfigForm_module_css_default.save,
|
|
233
|
-
disabled: blocked,
|
|
234
|
-
onClick: props.onSave,
|
|
235
|
-
children: props.t(state.saving ? "saving" : "save")
|
|
236
|
-
})]
|
|
237
|
-
})
|
|
238
|
-
]
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
//#endregion
|
|
242
|
-
//#region lib/types/client/AgentLoopCard.js
|
|
243
|
-
/**
|
|
244
|
-
* Render the agent loop's one-liner or its configuration form, as the Plugins page asks.
|
|
245
|
-
* @param props - the view asked for, locale copy, the form snapshot, and its actions.
|
|
246
|
-
* @returns the one-liner, or the form.
|
|
247
|
-
*/
|
|
248
|
-
function AgentLoopCard(props) {
|
|
249
|
-
const { t } = props;
|
|
250
|
-
const state = props.useAgentLoopCard((snapshot) => snapshot);
|
|
251
|
-
if (props.view === "summary") return t("agentLoopDescription");
|
|
252
|
-
return (0, react_jsx_runtime.jsx)(PluginConfigForm, {
|
|
253
|
-
t,
|
|
254
|
-
state,
|
|
255
|
-
onSave: props.save,
|
|
256
|
-
onDiscard: props.discard,
|
|
257
|
-
children: (0, react_jsx_runtime.jsx)(ValueField, {
|
|
258
|
-
id: "plugin-config-agent-loop-parallel",
|
|
259
|
-
label: t("agentLoopMaxParallel"),
|
|
260
|
-
hint: t("agentLoopMaxParallelHint"),
|
|
261
|
-
overriddenLabel: t("overridden"),
|
|
262
|
-
resetLabel: t("reset"),
|
|
263
|
-
invalidLabel: t("invalidNumber"),
|
|
264
|
-
numeric: true,
|
|
265
|
-
disabled: !state.writable,
|
|
266
|
-
...state.maxParallelToolCalls,
|
|
267
|
-
onEdit: (text) => {
|
|
268
|
-
props.edit("maxParallelToolCalls", text);
|
|
269
|
-
},
|
|
270
|
-
onReset: () => {
|
|
271
|
-
props.resetField("maxParallelToolCalls");
|
|
272
|
-
}
|
|
273
|
-
})
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
//#endregion
|
|
277
|
-
//#region lib/types/client/BashCard.js
|
|
278
|
-
/**
|
|
279
|
-
* Render the shell plugin's one-liner or its configuration form, as the Plugins page asks.
|
|
280
|
-
* @param props - the view asked for, locale copy, the form snapshot, and its actions.
|
|
281
|
-
* @returns the one-liner, or the form.
|
|
282
|
-
*/
|
|
283
|
-
function BashCard(props) {
|
|
284
|
-
const { t } = props;
|
|
285
|
-
const state = props.useBashCard((snapshot) => snapshot);
|
|
286
|
-
if (props.view === "summary") return t("bashDescription");
|
|
287
|
-
const disabled = !state.writable;
|
|
288
|
-
return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
|
|
289
|
-
t,
|
|
290
|
-
state,
|
|
291
|
-
onSave: props.save,
|
|
292
|
-
onDiscard: props.discard,
|
|
293
|
-
children: [(0, react_jsx_runtime.jsx)(ValueField, {
|
|
294
|
-
id: "plugin-config-bash-timeout",
|
|
295
|
-
label: t("bashTimeoutMs"),
|
|
296
|
-
hint: t("bashTimeoutMsHint"),
|
|
297
|
-
overriddenLabel: t("overridden"),
|
|
298
|
-
resetLabel: t("reset"),
|
|
299
|
-
invalidLabel: t("invalidNumber"),
|
|
300
|
-
numeric: true,
|
|
301
|
-
disabled,
|
|
302
|
-
...state.timeoutMs,
|
|
303
|
-
onEdit: (text) => {
|
|
304
|
-
props.edit("timeoutMs", text);
|
|
305
|
-
},
|
|
306
|
-
onReset: () => {
|
|
307
|
-
props.resetField("timeoutMs");
|
|
308
|
-
}
|
|
309
|
-
}), (0, react_jsx_runtime.jsx)(ValueField, {
|
|
310
|
-
id: "plugin-config-bash-output",
|
|
311
|
-
label: t("bashMaxOutputBytes"),
|
|
312
|
-
hint: t("bashMaxOutputBytesHint"),
|
|
313
|
-
overriddenLabel: t("overridden"),
|
|
314
|
-
resetLabel: t("reset"),
|
|
315
|
-
invalidLabel: t("invalidNumber"),
|
|
316
|
-
numeric: true,
|
|
317
|
-
disabled,
|
|
318
|
-
...state.maxOutputBytes,
|
|
319
|
-
onEdit: (text) => {
|
|
320
|
-
props.edit("maxOutputBytes", text);
|
|
321
|
-
},
|
|
322
|
-
onReset: () => {
|
|
323
|
-
props.resetField("maxOutputBytes");
|
|
324
|
-
}
|
|
325
|
-
})]
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
//#endregion
|
|
329
10
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/PluginsSettingsSection.module.css.mjs
|
|
330
|
-
const css
|
|
331
|
-
const tagId
|
|
332
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId
|
|
11
|
+
const css = ".pbvGtq_section{max-width:760px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.pbvGtq_heading{margin:0;font-size:18px;font-weight:600}.pbvGtq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px}.pbvGtq_tabs{border-bottom:.5px solid var(--dsw-alias-border-l2);align-items:flex-end;gap:22px;margin-top:2px;display:flex}.pbvGtq_tab{color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;padding:7px 1px 9px;font-size:13px;line-height:20px;position:relative}.pbvGtq_tab:hover,.pbvGtq_tab[data-active=true]{color:var(--dsw-alias-label-primary)}.pbvGtq_tab[data-active=true]:after,.pbvGtq_tab:focus-visible:after{background:var(--dsw-alias-label-primary);content:\"\";border-radius:2px 2px 0 0;height:2px;position:absolute;bottom:-1px;left:0;right:0}.pbvGtq_tab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;color:var(--dsw-alias-label-primary);border-radius:2px}.pbvGtq_panel{min-width:0;padding-top:2px}.pbvGtq_cards{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}.pbvGtq_empty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px}.pbvGtq_configurable{flex-direction:column;gap:10px;display:flex}.pbvGtq_presetSettings{flex-direction:column;gap:8px;display:flex}.pbvGtq_presetSettingsTitle{margin:0;font-size:15px;font-weight:600;line-height:22px}";
|
|
12
|
+
const tagId = "@deepseek-ai/dsh-client-ui-settings-plugins/PluginsSettingsSection.module.css";
|
|
13
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
333
14
|
const tag = document.createElement("style");
|
|
334
15
|
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
335
|
-
tag.dataset.pluginCss = tagId
|
|
336
|
-
tag.textContent = css
|
|
16
|
+
tag.dataset.pluginCss = tagId;
|
|
17
|
+
tag.textContent = css;
|
|
337
18
|
document.head.appendChild(tag);
|
|
338
19
|
}
|
|
339
20
|
var PluginsSettingsSection_module_css_default = {
|
|
@@ -447,1288 +128,15 @@ window.__ModuleLoader__.load({
|
|
|
447
128
|
});
|
|
448
129
|
}
|
|
449
130
|
//#endregion
|
|
450
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/SubagentLimitsFields.module.css.mjs
|
|
451
|
-
const css$2 = ".uedTFq_limits{grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:16px;display:grid}.uedTFq_limit{min-width:0}.uedTFq_limit input{font-variant-numeric:tabular-nums;min-width:0}.uedTFq_depthTable{border-collapse:collapse;border-block:.5px solid var(--dsw-alias-border-l2);width:100%;font:inherit;text-align:left;margin:8px 0}.uedTFq_depthTable th,.uedTFq_depthTable td{vertical-align:top;padding:6px 0}.uedTFq_depthTable th{font-variant-numeric:tabular-nums;width:24px;color:var(--dsw-alias-label-primary);padding-right:8px;font-weight:500}.uedTFq_depthTable tr+tr{border-top:.5px solid var(--dsw-alias-border-l2)}";
|
|
452
|
-
const tagId$2 = "@deepseek-ai/dsh-client-ui-settings-plugins/SubagentLimitsFields.module.css";
|
|
453
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
454
|
-
const tag = document.createElement("style");
|
|
455
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
456
|
-
tag.dataset.pluginCss = tagId$2;
|
|
457
|
-
tag.textContent = css$2;
|
|
458
|
-
document.head.appendChild(tag);
|
|
459
|
-
}
|
|
460
|
-
var SubagentLimitsFields_module_css_default = {
|
|
461
|
-
"depthTable": "uedTFq_depthTable",
|
|
462
|
-
"limit": "uedTFq_limit",
|
|
463
|
-
"limits": "uedTFq_limits"
|
|
464
|
-
};
|
|
465
|
-
//#endregion
|
|
466
|
-
//#region lib/types/client/SubagentLimitsFields.js
|
|
467
|
-
/**
|
|
468
|
-
* Render the depth and capacity fields with their original validation and reset behavior.
|
|
469
|
-
* @param props - Locale, staged fields, and edit callbacks.
|
|
470
|
-
* @returns Two responsive fields and their application rules.
|
|
471
|
-
*/
|
|
472
|
-
function SubagentLimitsFields(props) {
|
|
473
|
-
const { t, state } = props;
|
|
474
|
-
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
|
|
475
|
-
className: SubagentLimitsFields_module_css_default.limits,
|
|
476
|
-
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
477
|
-
className: SubagentLimitsFields_module_css_default.limit,
|
|
478
|
-
children: (0, react_jsx_runtime.jsx)(ValueField, {
|
|
479
|
-
id: "plugin-config-subagent-depth",
|
|
480
|
-
label: t("subagentMaxDepth"),
|
|
481
|
-
help: {
|
|
482
|
-
label: t("subagentDepthHelpLabel"),
|
|
483
|
-
content: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
484
|
-
(0, react_jsx_runtime.jsx)("p", { children: t("subagentDepthHelp") }),
|
|
485
|
-
(0, react_jsx_runtime.jsx)("table", {
|
|
486
|
-
className: SubagentLimitsFields_module_css_default.depthTable,
|
|
487
|
-
"aria-label": t("subagentDepthHelpLabel"),
|
|
488
|
-
children: (0, react_jsx_runtime.jsxs)("tbody", { children: [(0, react_jsx_runtime.jsxs)("tr", { children: [(0, react_jsx_runtime.jsx)("th", {
|
|
489
|
-
scope: "row",
|
|
490
|
-
children: 0
|
|
491
|
-
}), (0, react_jsx_runtime.jsx)("td", { children: t("subagentDepthZero") })] }), (0, react_jsx_runtime.jsxs)("tr", { children: [(0, react_jsx_runtime.jsx)("th", {
|
|
492
|
-
scope: "row",
|
|
493
|
-
children: 1
|
|
494
|
-
}), (0, react_jsx_runtime.jsx)("td", { children: t("subagentDepthOne") })] })] })
|
|
495
|
-
}),
|
|
496
|
-
(0, react_jsx_runtime.jsx)("p", { children: t("subagentDepthOverride") })
|
|
497
|
-
] })
|
|
498
|
-
},
|
|
499
|
-
overriddenLabel: t("overridden"),
|
|
500
|
-
resetLabel: t("reset"),
|
|
501
|
-
invalidLabel: t("subagentDepthInvalid"),
|
|
502
|
-
numeric: true,
|
|
503
|
-
disabled: !state.writable || state.saving,
|
|
504
|
-
...state.maxDepth,
|
|
505
|
-
onEdit: (text) => {
|
|
506
|
-
props.edit("maxDepth", text);
|
|
507
|
-
},
|
|
508
|
-
onReset: () => {
|
|
509
|
-
props.resetField("maxDepth");
|
|
510
|
-
}
|
|
511
|
-
})
|
|
512
|
-
}), (0, react_jsx_runtime.jsx)("div", {
|
|
513
|
-
className: SubagentLimitsFields_module_css_default.limit,
|
|
514
|
-
children: (0, react_jsx_runtime.jsx)(ValueField, {
|
|
515
|
-
id: "plugin-config-subagent-capacity",
|
|
516
|
-
label: t("subagentMaxActive"),
|
|
517
|
-
help: {
|
|
518
|
-
label: t("subagentCapacityHelpLabel"),
|
|
519
|
-
content: (0, react_jsx_runtime.jsx)("p", { children: t("subagentCapacityHelp") })
|
|
520
|
-
},
|
|
521
|
-
overriddenLabel: t("overridden"),
|
|
522
|
-
resetLabel: t("reset"),
|
|
523
|
-
invalidLabel: t("subagentCapacityInvalid"),
|
|
524
|
-
numeric: true,
|
|
525
|
-
disabled: !state.writable || state.saving,
|
|
526
|
-
...state.maxActiveSubagents,
|
|
527
|
-
onEdit: (text) => {
|
|
528
|
-
props.edit("maxActiveSubagents", text);
|
|
529
|
-
},
|
|
530
|
-
onReset: () => {
|
|
531
|
-
props.resetField("maxActiveSubagents");
|
|
532
|
-
}
|
|
533
|
-
})
|
|
534
|
-
})]
|
|
535
|
-
}) });
|
|
536
|
-
}
|
|
537
|
-
//#endregion
|
|
538
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/SubagentModelSelectionFields.module.css.mjs
|
|
539
|
-
const css$1 = "._2QGtya_permission{gap:6px;padding:12px 0;display:grid}._2QGtya_toggleRow{color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:flex-start;gap:16px;font-size:13px;line-height:1.5;display:flex}._2QGtya_toggleLabel{flex:1;min-width:0}._2QGtya_selection{gap:10px;display:grid}._2QGtya_hint,._2QGtya_notice,._2QGtya_invalid,._2QGtya_conflict{margin:0;font-size:12px;line-height:1.5}._2QGtya_hint,._2QGtya_notice{color:var(--dsw-alias-label-tertiary)}._2QGtya_invalid,._2QGtya_conflict{color:var(--dsw-alias-state-error-primary)}._2QGtya_catalogError{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:12px;font-size:12px;display:flex}._2QGtya_catalogError button{color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border:0;padding:0}._2QGtya_models{border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;gap:6px;min-width:0;max-height:280px;margin:0;padding:10px;display:grid;overflow:auto}._2QGtya_models legend{color:var(--dsw-alias-label-secondary);padding:0 4px;font-size:12px}._2QGtya_modelGroup{gap:6px;display:grid}._2QGtya_modelGroup+._2QGtya_modelGroup{border-top:.5px solid var(--dsw-alias-border-l3);margin-top:4px;padding-top:10px}._2QGtya_providerName{color:var(--dsw-alias-label-tertiary);padding:0 6px;font-size:11px;font-weight:500}._2QGtya_model{cursor:pointer;border-radius:6px;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;min-width:0;padding:6px;display:grid}._2QGtya_model:hover{background:var(--dsw-alias-bg-layer-4)}._2QGtya_modelName,._2QGtya_route{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}._2QGtya_modelName{color:var(--dsw-alias-label-primary);font-size:13px}._2QGtya_route{color:var(--dsw-alias-label-tertiary);margin-top:2px;font-size:11px}._2QGtya_unavailable{color:var(--dsw-alias-label-tertiary);font-size:11px}";
|
|
540
|
-
const tagId$1 = "@deepseek-ai/dsh-client-ui-settings-plugins/SubagentModelSelectionFields.module.css";
|
|
541
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
542
|
-
const tag = document.createElement("style");
|
|
543
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
544
|
-
tag.dataset.pluginCss = tagId$1;
|
|
545
|
-
tag.textContent = css$1;
|
|
546
|
-
document.head.appendChild(tag);
|
|
547
|
-
}
|
|
548
|
-
var SubagentModelSelectionFields_module_css_default = {
|
|
549
|
-
"catalogError": "_2QGtya_catalogError",
|
|
550
|
-
"conflict": "_2QGtya_conflict",
|
|
551
|
-
"hint": "_2QGtya_hint",
|
|
552
|
-
"invalid": "_2QGtya_invalid",
|
|
553
|
-
"model": "_2QGtya_model",
|
|
554
|
-
"modelGroup": "_2QGtya_modelGroup",
|
|
555
|
-
"modelName": "_2QGtya_modelName",
|
|
556
|
-
"models": "_2QGtya_models",
|
|
557
|
-
"notice": "_2QGtya_notice",
|
|
558
|
-
"permission": "_2QGtya_permission",
|
|
559
|
-
"providerName": "_2QGtya_providerName",
|
|
560
|
-
"route": "_2QGtya_route",
|
|
561
|
-
"selection": "_2QGtya_selection",
|
|
562
|
-
"toggleLabel": "_2QGtya_toggleLabel",
|
|
563
|
-
"toggleRow": "_2QGtya_toggleRow",
|
|
564
|
-
"unavailable": "_2QGtya_unavailable"
|
|
565
|
-
};
|
|
566
|
-
//#endregion
|
|
567
|
-
//#region lib/types/client/SubagentModelSelectionFields.js
|
|
568
|
-
/** User control for model-selectable subagent delegation in new sessions. */
|
|
569
|
-
/**
|
|
570
|
-
* Render the default-off preference and its exact adapter-route choices.
|
|
571
|
-
* @param props - locale copy, the card snapshot, and its toggle action.
|
|
572
|
-
* @returns the model permission and route choices inside the shared card.
|
|
573
|
-
*/
|
|
574
|
-
function SubagentModelSelectionFields(props) {
|
|
575
|
-
const { t, state } = props;
|
|
576
|
-
const availableGroups = /* @__PURE__ */ new Map();
|
|
577
|
-
const unavailable = [];
|
|
578
|
-
for (const candidate of state.candidates) {
|
|
579
|
-
if (!candidate.available) {
|
|
580
|
-
unavailable.push(candidate);
|
|
581
|
-
continue;
|
|
582
|
-
}
|
|
583
|
-
const group = availableGroups.get(candidate.provider);
|
|
584
|
-
if (group === void 0) availableGroups.set(candidate.provider, {
|
|
585
|
-
providerName: candidate.providerName,
|
|
586
|
-
candidates: [candidate]
|
|
587
|
-
});
|
|
588
|
-
else group.candidates.push(candidate);
|
|
589
|
-
}
|
|
590
|
-
const renderCandidate = (candidate) => (0, react_jsx_runtime.jsxs)("label", {
|
|
591
|
-
className: SubagentModelSelectionFields_module_css_default.model,
|
|
592
|
-
children: [
|
|
593
|
-
(0, react_jsx_runtime.jsx)("input", {
|
|
594
|
-
type: "checkbox",
|
|
595
|
-
checked: candidate.selected,
|
|
596
|
-
disabled: !state.writable || state.saving,
|
|
597
|
-
onChange: () => {
|
|
598
|
-
props.toggleModel(candidate.key);
|
|
599
|
-
}
|
|
600
|
-
}),
|
|
601
|
-
(0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("span", {
|
|
602
|
-
className: SubagentModelSelectionFields_module_css_default.modelName,
|
|
603
|
-
children: candidate.modelName
|
|
604
|
-
}), (0, react_jsx_runtime.jsx)("span", {
|
|
605
|
-
className: SubagentModelSelectionFields_module_css_default.route,
|
|
606
|
-
children: `${candidate.providerName} · ${candidate.provider}/${candidate.model}`
|
|
607
|
-
})] }),
|
|
608
|
-
!candidate.available ? (0, react_jsx_runtime.jsx)("span", {
|
|
609
|
-
className: SubagentModelSelectionFields_module_css_default.unavailable,
|
|
610
|
-
children: t("subagentModelSelectionUnavailable")
|
|
611
|
-
}) : null
|
|
612
|
-
]
|
|
613
|
-
}, candidate.key);
|
|
614
|
-
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
615
|
-
(0, react_jsx_runtime.jsxs)("div", {
|
|
616
|
-
className: SubagentModelSelectionFields_module_css_default.permission,
|
|
617
|
-
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
618
|
-
className: SubagentModelSelectionFields_module_css_default.toggleRow,
|
|
619
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
620
|
-
className: SubagentModelSelectionFields_module_css_default.toggleLabel,
|
|
621
|
-
children: t("subagentModelSelectionToggle")
|
|
622
|
-
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
623
|
-
checked: state.enabled,
|
|
624
|
-
label: t("subagentModelSelectionToggle"),
|
|
625
|
-
disabled: !state.writable || state.saving,
|
|
626
|
-
onChange: props.toggleEnabled
|
|
627
|
-
})]
|
|
628
|
-
}), (0, react_jsx_runtime.jsx)("p", {
|
|
629
|
-
className: SubagentModelSelectionFields_module_css_default.hint,
|
|
630
|
-
children: t(state.enabled ? "subagentModelSelectionChoose" : "subagentModelSelectionOff")
|
|
631
|
-
})]
|
|
632
|
-
}),
|
|
633
|
-
state.enabled ? (0, react_jsx_runtime.jsxs)("div", {
|
|
634
|
-
className: SubagentModelSelectionFields_module_css_default.selection,
|
|
635
|
-
children: [
|
|
636
|
-
state.catalogStatus === "loading" ? (0, react_jsx_runtime.jsx)("p", {
|
|
637
|
-
className: SubagentModelSelectionFields_module_css_default.notice,
|
|
638
|
-
role: "status",
|
|
639
|
-
children: t("subagentModelSelectionLoading")
|
|
640
|
-
}) : null,
|
|
641
|
-
state.catalogStatus === "error" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
642
|
-
className: SubagentModelSelectionFields_module_css_default.catalogError,
|
|
643
|
-
role: "alert",
|
|
644
|
-
children: [(0, react_jsx_runtime.jsx)("span", { children: t("subagentModelSelectionLoadFailed") }), (0, react_jsx_runtime.jsx)("button", {
|
|
645
|
-
type: "button",
|
|
646
|
-
disabled: state.saving,
|
|
647
|
-
onClick: props.retryCatalog,
|
|
648
|
-
children: t("subagentModelSelectionRetry")
|
|
649
|
-
})]
|
|
650
|
-
}) : null,
|
|
651
|
-
state.catalogPartial ? (0, react_jsx_runtime.jsx)("p", {
|
|
652
|
-
className: SubagentModelSelectionFields_module_css_default.notice,
|
|
653
|
-
children: t("subagentModelSelectionPartial")
|
|
654
|
-
}) : null,
|
|
655
|
-
state.candidates.length > 0 ? (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
656
|
-
className: SubagentModelSelectionFields_module_css_default.models,
|
|
657
|
-
children: [
|
|
658
|
-
(0, react_jsx_runtime.jsx)("legend", { children: t("subagentModelSelectionAllowed") }),
|
|
659
|
-
[...availableGroups].map(([provider, group]) => (0, react_jsx_runtime.jsxs)("div", {
|
|
660
|
-
className: SubagentModelSelectionFields_module_css_default.modelGroup,
|
|
661
|
-
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
662
|
-
className: SubagentModelSelectionFields_module_css_default.providerName,
|
|
663
|
-
children: group.providerName
|
|
664
|
-
}), group.candidates.map(renderCandidate)]
|
|
665
|
-
}, provider)),
|
|
666
|
-
unavailable.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
667
|
-
className: SubagentModelSelectionFields_module_css_default.modelGroup,
|
|
668
|
-
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
669
|
-
className: SubagentModelSelectionFields_module_css_default.providerName,
|
|
670
|
-
children: t("subagentModelSelectionUnavailableGroup")
|
|
671
|
-
}), unavailable.map(renderCandidate)]
|
|
672
|
-
}) : null
|
|
673
|
-
]
|
|
674
|
-
}) : state.catalogStatus === "ready" ? (0, react_jsx_runtime.jsx)("p", {
|
|
675
|
-
className: SubagentModelSelectionFields_module_css_default.notice,
|
|
676
|
-
children: t("subagentModelSelectionEmpty")
|
|
677
|
-
}) : null,
|
|
678
|
-
state.invalid ? (0, react_jsx_runtime.jsx)("p", {
|
|
679
|
-
className: SubagentModelSelectionFields_module_css_default.invalid,
|
|
680
|
-
children: t("subagentModelSelectionRequired")
|
|
681
|
-
}) : null
|
|
682
|
-
]
|
|
683
|
-
}) : null,
|
|
684
|
-
state.conflicted ? (0, react_jsx_runtime.jsx)("p", {
|
|
685
|
-
className: SubagentModelSelectionFields_module_css_default.conflict,
|
|
686
|
-
role: "status",
|
|
687
|
-
children: t("subagentModelSelectionConflict")
|
|
688
|
-
}) : null
|
|
689
|
-
] });
|
|
690
|
-
}
|
|
691
|
-
//#endregion
|
|
692
|
-
//#region lib/types/client/subagent-card-controller.js
|
|
693
|
-
/** Shared presentation and actions for the two Host-owned Subagent settings sections. */
|
|
694
|
-
/**
|
|
695
|
-
* Derive the shared card state without duplicating either form's subscriptions.
|
|
696
|
-
* @param limits - Current delegation-limit form.
|
|
697
|
-
* @param models - Current model-authorization form.
|
|
698
|
-
* @returns Availability and settlement across the sections this Host serves.
|
|
699
|
-
*/
|
|
700
|
-
function subagentCardShell(limits, models) {
|
|
701
|
-
const sections = [limits, models].filter((section) => section.available);
|
|
702
|
-
return {
|
|
703
|
-
available: sections.length > 0,
|
|
704
|
-
writable: sections.every((section) => section.writable),
|
|
705
|
-
dirty: sections.some((section) => section.dirty),
|
|
706
|
-
invalid: sections.some((section) => section.invalid) || models.available && models.dirty && models.conflicted,
|
|
707
|
-
saving: sections.some((section) => section.saving),
|
|
708
|
-
failed: sections.some((section) => section.failed)
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* Compose one card from the existing forms; each write retains its namespace revision fence.
|
|
713
|
-
* @param limits - Limit form source and actions.
|
|
714
|
-
* @param models - Model form source and actions.
|
|
715
|
-
* @returns Framework-bound sources and shared save/discard actions.
|
|
716
|
-
*/
|
|
717
|
-
function subagentCardFace(limits, models) {
|
|
718
|
-
return {
|
|
719
|
-
hooks: {
|
|
720
|
-
...limits.hooks,
|
|
721
|
-
...models.hooks
|
|
722
|
-
},
|
|
723
|
-
editLimit: limits.edit,
|
|
724
|
-
resetLimit: limits.resetField,
|
|
725
|
-
toggleEnabled: models.toggleEnabled,
|
|
726
|
-
toggleModel: models.toggleModel,
|
|
727
|
-
retryCatalog: models.retryCatalog,
|
|
728
|
-
save: () => {
|
|
729
|
-
const limitState = limits.hooks.subagentLimitsCard.getSnapshot();
|
|
730
|
-
const modelState = models.hooks.subagentModelSelectionCard.getSnapshot();
|
|
731
|
-
const state = subagentCardShell(limitState, modelState);
|
|
732
|
-
if (!state.available || !state.writable || !state.dirty || state.invalid || state.saving) return;
|
|
733
|
-
if (modelState.available && modelState.dirty) models.save();
|
|
734
|
-
if (limitState.available && limitState.dirty) limits.save();
|
|
735
|
-
},
|
|
736
|
-
discard: () => {
|
|
737
|
-
if (subagentCardShell(limits.hooks.subagentLimitsCard.getSnapshot(), models.hooks.subagentModelSelectionCard.getSnapshot()).saving) return;
|
|
738
|
-
limits.discard();
|
|
739
|
-
models.discard();
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
//#endregion
|
|
744
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugins/src/client/SubagentCard.module.css.mjs
|
|
745
|
-
const css = ".UYsYFG_section{min-width:0;padding:16px 0}.UYsYFG_heading{color:var(--dsw-alias-label-primary);margin:0;font-size:13px;font-weight:600;line-height:1.5}";
|
|
746
|
-
const tagId = "@deepseek-ai/dsh-client-ui-settings-plugins/SubagentCard.module.css";
|
|
747
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
748
|
-
const tag = document.createElement("style");
|
|
749
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugins";
|
|
750
|
-
tag.dataset.pluginCss = tagId;
|
|
751
|
-
tag.textContent = css;
|
|
752
|
-
document.head.appendChild(tag);
|
|
753
|
-
}
|
|
754
|
-
var SubagentCard_module_css_default = {
|
|
755
|
-
"heading": "UYsYFG_heading",
|
|
756
|
-
"section": "UYsYFG_section"
|
|
757
|
-
};
|
|
758
|
-
//#endregion
|
|
759
|
-
//#region lib/types/client/SubagentCard.js
|
|
760
|
-
/** One settings card for Subagent delegation limits and model authorization. */
|
|
761
|
-
/**
|
|
762
|
-
* Render the available Subagent settings with one configuration page and save footer.
|
|
763
|
-
* @param props - Locale, both form snapshots, and their shared actions.
|
|
764
|
-
* @returns The summary or the available settings form.
|
|
765
|
-
*/
|
|
766
|
-
function SubagentCard(props) {
|
|
767
|
-
const { t } = props;
|
|
768
|
-
const limits = props.useSubagentLimitsCard((snapshot) => snapshot);
|
|
769
|
-
const models = props.useSubagentModelSelectionCard((snapshot) => snapshot);
|
|
770
|
-
const headingId = (0, react.useId)();
|
|
771
|
-
if (props.view === "summary") return t("subagentDescription");
|
|
772
|
-
const state = subagentCardShell(limits, models);
|
|
773
|
-
return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
|
|
774
|
-
t,
|
|
775
|
-
state,
|
|
776
|
-
onSave: props.save,
|
|
777
|
-
onDiscard: props.discard,
|
|
778
|
-
children: [limits.available ? (0, react_jsx_runtime.jsxs)("section", {
|
|
779
|
-
className: SubagentCard_module_css_default.section,
|
|
780
|
-
"aria-labelledby": `${headingId}-limits`,
|
|
781
|
-
children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
782
|
-
className: SubagentCard_module_css_default.heading,
|
|
783
|
-
id: `${headingId}-limits`,
|
|
784
|
-
children: t("subagentLimitsTitle")
|
|
785
|
-
}), (0, react_jsx_runtime.jsx)(SubagentLimitsFields, {
|
|
786
|
-
t,
|
|
787
|
-
state: {
|
|
788
|
-
...limits,
|
|
789
|
-
saving: state.saving
|
|
790
|
-
},
|
|
791
|
-
edit: props.editLimit,
|
|
792
|
-
resetField: props.resetLimit
|
|
793
|
-
})]
|
|
794
|
-
}) : null, models.available ? (0, react_jsx_runtime.jsxs)("section", {
|
|
795
|
-
className: SubagentCard_module_css_default.section,
|
|
796
|
-
"aria-labelledby": `${headingId}-models`,
|
|
797
|
-
children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
798
|
-
className: SubagentCard_module_css_default.heading,
|
|
799
|
-
id: `${headingId}-models`,
|
|
800
|
-
children: t("subagentModelSelectionTitle")
|
|
801
|
-
}), (0, react_jsx_runtime.jsx)(SubagentModelSelectionFields, {
|
|
802
|
-
t,
|
|
803
|
-
state: {
|
|
804
|
-
...models,
|
|
805
|
-
saving: state.saving
|
|
806
|
-
},
|
|
807
|
-
toggleEnabled: props.toggleEnabled,
|
|
808
|
-
toggleModel: props.toggleModel,
|
|
809
|
-
retryCatalog: props.retryCatalog
|
|
810
|
-
})]
|
|
811
|
-
}) : null]
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
//#endregion
|
|
815
|
-
//#region lib/types/client/card-form.js
|
|
816
|
-
/**
|
|
817
|
-
* Shared form model behind every plugin card.
|
|
818
|
-
*
|
|
819
|
-
* A card stages what the user types and writes it only when they save. Each
|
|
820
|
-
* settings write is a durable, revision-fenced document mutation, so a control
|
|
821
|
-
* that committed as it settled turned one edit into a write the user never
|
|
822
|
-
* asked for and could not preview; staged text makes what is on screen exactly
|
|
823
|
-
* what a save would store.
|
|
824
|
-
*
|
|
825
|
-
* A field shows its effective value — the user layer over the composition
|
|
826
|
-
* layer over the schema default — and whether the user layer carries it. That
|
|
827
|
-
* presence, not a value comparison, is what marks a field overridden: an
|
|
828
|
-
* override equal to the composition default is still an override.
|
|
829
|
-
*/
|
|
830
|
-
/**
|
|
831
|
-
* A whole-number field. An empty draft clears the field; any other draft that
|
|
832
|
-
* is not a finite number blocks the save.
|
|
833
|
-
* @param field - field name inside the namespace section.
|
|
834
|
-
* @returns the field's conversion spec.
|
|
835
|
-
*/
|
|
836
|
-
function numberField(field) {
|
|
837
|
-
return {
|
|
838
|
-
field,
|
|
839
|
-
format: (value) => typeof value === "number" ? String(value) : "",
|
|
840
|
-
parse: (text) => {
|
|
841
|
-
const trimmed = text.trim();
|
|
842
|
-
if (trimmed === "") return { kind: "clear" };
|
|
843
|
-
const parsed = Number(trimmed);
|
|
844
|
-
return Number.isFinite(parsed) ? {
|
|
845
|
-
kind: "set",
|
|
846
|
-
value: parsed
|
|
847
|
-
} : void 0;
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
/**
|
|
852
|
-
* A free-text field. An empty draft clears the field, so emptying the control
|
|
853
|
-
* and saving is the same gesture as resetting it.
|
|
854
|
-
* @param field - field name inside the namespace section.
|
|
855
|
-
* @returns the field's conversion spec.
|
|
856
|
-
*/
|
|
857
|
-
function textField(field) {
|
|
858
|
-
return {
|
|
859
|
-
field,
|
|
860
|
-
format: (value) => typeof value === "string" ? value : "",
|
|
861
|
-
parse: (text) => {
|
|
862
|
-
const trimmed = text.trim();
|
|
863
|
-
return trimmed === "" ? { kind: "clear" } : {
|
|
864
|
-
kind: "set",
|
|
865
|
-
value: trimmed
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* Stages one card's edits over one settings namespace and writes them on save.
|
|
872
|
-
*
|
|
873
|
-
* The form publishes through a snapshot store because slot components read
|
|
874
|
-
* through a snapshot selector, while both the scope and the local drafts
|
|
875
|
-
* change underneath; every projection is rebuilt from the two together.
|
|
876
|
-
*/
|
|
877
|
-
var CardForm = class {
|
|
878
|
-
scope;
|
|
879
|
-
specs;
|
|
880
|
-
secretSpecs;
|
|
881
|
-
staged = /* @__PURE__ */ new Map();
|
|
882
|
-
listeners = /* @__PURE__ */ new Set();
|
|
883
|
-
saving = false;
|
|
884
|
-
failed = false;
|
|
885
|
-
/**
|
|
886
|
-
* @param scope - the bound settings scope for this card's namespace.
|
|
887
|
-
* @param specs - the section fields this card edits.
|
|
888
|
-
* @param secrets - the card's write-only controls, written outside the section.
|
|
889
|
-
*/
|
|
890
|
-
constructor(scope, specs, secrets = []) {
|
|
891
|
-
this.scope = scope;
|
|
892
|
-
this.specs = new Map(specs.map((spec) => [spec.field, spec]));
|
|
893
|
-
this.secretSpecs = new Map(secrets.map((spec) => [spec.field, spec]));
|
|
894
|
-
scope.subscribe(() => {
|
|
895
|
-
this.publish();
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
/**
|
|
899
|
-
* Publish a projection of this form, rebuilt whenever the scope or a draft changes.
|
|
900
|
-
* @param project - build the card's state from the form's current reads.
|
|
901
|
-
* @returns the store the card's component reads through its bound selector.
|
|
902
|
-
*/
|
|
903
|
-
bind(project) {
|
|
904
|
-
const store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(project());
|
|
905
|
-
this.listeners.add(() => {
|
|
906
|
-
store.set(project());
|
|
907
|
-
});
|
|
908
|
-
return store;
|
|
909
|
-
}
|
|
910
|
-
/**
|
|
911
|
-
* Read the card-level state: what the Host serves, and what a save would do.
|
|
912
|
-
* @returns the form state every card shares.
|
|
913
|
-
*/
|
|
914
|
-
shell() {
|
|
915
|
-
const snapshot = this.scope.getSnapshot();
|
|
916
|
-
const plan = this.plan();
|
|
917
|
-
return {
|
|
918
|
-
available: snapshot.status === "ready",
|
|
919
|
-
writable: snapshot.writable,
|
|
920
|
-
dirty: plan.length > 0,
|
|
921
|
-
invalid: plan.some((item) => item.run === void 0),
|
|
922
|
-
saving: this.saving,
|
|
923
|
-
failed: this.failed
|
|
924
|
-
};
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* Read one control's state.
|
|
928
|
-
* @param field - field name of a section field or of a write-only control.
|
|
929
|
-
* @returns the draft text, whether a save would leave an override, and whether it is invalid.
|
|
930
|
-
*/
|
|
931
|
-
field(field) {
|
|
932
|
-
const staged = this.staged.get(field);
|
|
933
|
-
if (this.secretSpecs.has(field)) return {
|
|
934
|
-
text: staged?.text ?? "",
|
|
935
|
-
overridden: false,
|
|
936
|
-
invalid: false
|
|
937
|
-
};
|
|
938
|
-
const spec = this.spec(field);
|
|
939
|
-
if (staged === void 0) return {
|
|
940
|
-
text: spec.format(this.sectionValue(field)),
|
|
941
|
-
overridden: this.stored(field),
|
|
942
|
-
invalid: false
|
|
943
|
-
};
|
|
944
|
-
const write = staged.clear ? { kind: "clear" } : spec.parse(staged.text);
|
|
945
|
-
return {
|
|
946
|
-
text: staged.text,
|
|
947
|
-
overridden: write?.kind === "set",
|
|
948
|
-
invalid: write === void 0
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* Build the edit, reset, save, and discard actions bound to this form.
|
|
953
|
-
* @returns the actions a card's slot entry injects.
|
|
954
|
-
*/
|
|
955
|
-
actions() {
|
|
956
|
-
return {
|
|
957
|
-
edit: (field, text) => {
|
|
958
|
-
this.stage(field, {
|
|
959
|
-
text,
|
|
960
|
-
clear: false
|
|
961
|
-
});
|
|
962
|
-
},
|
|
963
|
-
resetField: (field) => {
|
|
964
|
-
this.stage(field, {
|
|
965
|
-
text: this.spec(field).format(this.baseValue(field)),
|
|
966
|
-
clear: true
|
|
967
|
-
});
|
|
968
|
-
},
|
|
969
|
-
save: () => {
|
|
970
|
-
this.save();
|
|
971
|
-
},
|
|
972
|
-
discard: () => {
|
|
973
|
-
if (this.staged.size === 0 && !this.failed) return;
|
|
974
|
-
this.staged.clear();
|
|
975
|
-
this.failed = false;
|
|
976
|
-
this.publish();
|
|
977
|
-
}
|
|
978
|
-
};
|
|
979
|
-
}
|
|
980
|
-
/**
|
|
981
|
-
* Write every staged edit, then re-seed from what the Host accepted.
|
|
982
|
-
*
|
|
983
|
-
* The Host is the only authority on whether a value was accepted — its
|
|
984
|
-
* validators own the constraints no schema can express — so the outcome is
|
|
985
|
-
* read back from the section rather than predicted here. A save that did not
|
|
986
|
-
* land keeps its drafts, so the user can correct them instead of retyping.
|
|
987
|
-
* @returns settlement after every write and the read-back.
|
|
988
|
-
*/
|
|
989
|
-
async save() {
|
|
990
|
-
const plan = this.plan();
|
|
991
|
-
const writes = plan.flatMap((item) => item.run === void 0 ? [] : [item.run]);
|
|
992
|
-
if (plan.length === 0 || this.saving || writes.length !== plan.length) return;
|
|
993
|
-
this.saving = true;
|
|
994
|
-
this.failed = false;
|
|
995
|
-
this.publish();
|
|
996
|
-
let landed = true;
|
|
997
|
-
for (const write of writes) landed = await write() && landed;
|
|
998
|
-
if (landed) this.staged.clear();
|
|
999
|
-
this.saving = false;
|
|
1000
|
-
this.failed = !landed;
|
|
1001
|
-
this.publish();
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* Every staged edit a save would write. An entry whose draft is not a value
|
|
1005
|
-
* its field accepts carries no write: the form is still dirty, and the save
|
|
1006
|
-
* refuses rather than dropping the edit.
|
|
1007
|
-
* @returns the planned writes, in the order the fields were staged.
|
|
1008
|
-
*/
|
|
1009
|
-
plan() {
|
|
1010
|
-
const plan = [];
|
|
1011
|
-
for (const [field, staged] of this.staged) {
|
|
1012
|
-
const secret = this.secretSpecs.get(field);
|
|
1013
|
-
if (secret !== void 0) {
|
|
1014
|
-
const value = staged.text.trim();
|
|
1015
|
-
if (value !== "") plan.push({
|
|
1016
|
-
field,
|
|
1017
|
-
run: () => secret.write(value)
|
|
1018
|
-
});
|
|
1019
|
-
continue;
|
|
1020
|
-
}
|
|
1021
|
-
const spec = this.spec(field);
|
|
1022
|
-
if (staged.clear) {
|
|
1023
|
-
if (this.stored(field)) plan.push({
|
|
1024
|
-
field,
|
|
1025
|
-
run: () => this.clear(field)
|
|
1026
|
-
});
|
|
1027
|
-
continue;
|
|
1028
|
-
}
|
|
1029
|
-
if (staged.text === spec.format(this.sectionValue(field))) continue;
|
|
1030
|
-
const write = spec.parse(staged.text);
|
|
1031
|
-
if (write === void 0) plan.push({
|
|
1032
|
-
field,
|
|
1033
|
-
run: void 0
|
|
1034
|
-
});
|
|
1035
|
-
else if (write.kind === "clear") plan.push({
|
|
1036
|
-
field,
|
|
1037
|
-
run: () => this.clear(field)
|
|
1038
|
-
});
|
|
1039
|
-
else plan.push({
|
|
1040
|
-
field,
|
|
1041
|
-
run: () => this.store(field, write.value)
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
return plan;
|
|
1045
|
-
}
|
|
1046
|
-
async clear(field) {
|
|
1047
|
-
await this.scope.unset(field);
|
|
1048
|
-
return !this.stored(field);
|
|
1049
|
-
}
|
|
1050
|
-
async store(field, value) {
|
|
1051
|
-
await this.scope.set(field, value);
|
|
1052
|
-
return this.userLayer()?.[field] === value;
|
|
1053
|
-
}
|
|
1054
|
-
stage(field, edit) {
|
|
1055
|
-
this.staged.set(field, edit);
|
|
1056
|
-
this.failed = false;
|
|
1057
|
-
this.publish();
|
|
1058
|
-
}
|
|
1059
|
-
spec(field) {
|
|
1060
|
-
const spec = this.specs.get(field);
|
|
1061
|
-
if (spec === void 0) throw new Error(`plugin card has no field ${field}`);
|
|
1062
|
-
return spec;
|
|
1063
|
-
}
|
|
1064
|
-
snapshotOf() {
|
|
1065
|
-
return this.scope.getSnapshot();
|
|
1066
|
-
}
|
|
1067
|
-
sectionValue(field) {
|
|
1068
|
-
return this.snapshotOf().value?.[field];
|
|
1069
|
-
}
|
|
1070
|
-
baseValue(field) {
|
|
1071
|
-
return this.snapshotOf().base?.[field];
|
|
1072
|
-
}
|
|
1073
|
-
userLayer() {
|
|
1074
|
-
return this.snapshotOf().user;
|
|
1075
|
-
}
|
|
1076
|
-
stored(field) {
|
|
1077
|
-
const user = this.userLayer();
|
|
1078
|
-
return user !== void 0 && Object.hasOwn(user, field);
|
|
1079
|
-
}
|
|
1080
|
-
publish() {
|
|
1081
|
-
for (const listener of this.listeners) listener();
|
|
1082
|
-
}
|
|
1083
|
-
};
|
|
1084
|
-
//#endregion
|
|
1085
|
-
//#region lib/types/client/subagent-limits-card-controller.js
|
|
1086
|
-
/** Staged delegation limits backed by the Host's subagent settings section. */
|
|
1087
|
-
function limitField(field, minimum) {
|
|
1088
|
-
const numeric = numberField(field);
|
|
1089
|
-
return {
|
|
1090
|
-
...numeric,
|
|
1091
|
-
parse: (text) => {
|
|
1092
|
-
const write = numeric.parse(text);
|
|
1093
|
-
if (write?.kind !== "set") return write;
|
|
1094
|
-
const value = write.value;
|
|
1095
|
-
return Number.isSafeInteger(value) && value >= minimum && !Object.is(value, -0) ? write : void 0;
|
|
1096
|
-
}
|
|
1097
|
-
};
|
|
1098
|
-
}
|
|
1099
|
-
/** Bind two independently resettable limits to one staged settings form. */
|
|
1100
|
-
var SubagentLimitsCardController = class {
|
|
1101
|
-
form;
|
|
1102
|
-
store;
|
|
1103
|
-
/** @param scope - The Host's `subagent` settings section. */
|
|
1104
|
-
constructor(scope) {
|
|
1105
|
-
this.form = new CardForm(scope, [limitField("maxDepth", 0), limitField("maxActiveSubagents", 1)]);
|
|
1106
|
-
this.store = this.form.bind(() => ({
|
|
1107
|
-
...this.form.shell(),
|
|
1108
|
-
maxDepth: this.form.field("maxDepth"),
|
|
1109
|
-
maxActiveSubagents: this.form.field("maxActiveSubagents")
|
|
1110
|
-
}));
|
|
1111
|
-
}
|
|
1112
|
-
/**
|
|
1113
|
-
* Bind the limits editor to the slot renderer.
|
|
1114
|
-
* @returns The limits snapshot and staged write actions.
|
|
1115
|
-
*/
|
|
1116
|
-
inject() {
|
|
1117
|
-
return {
|
|
1118
|
-
hooks: { subagentLimitsCard: this.store },
|
|
1119
|
-
...this.form.actions()
|
|
1120
|
-
};
|
|
1121
|
-
}
|
|
1122
|
-
};
|
|
1123
|
-
//#endregion
|
|
1124
|
-
//#region lib/types/client/WebSearchCard.js
|
|
1125
|
-
/**
|
|
1126
|
-
* Render the web-search provider's one-liner or its configuration form, as the Plugins page asks.
|
|
1127
|
-
* @param props - the view asked for, locale copy, the form snapshot, and its actions.
|
|
1128
|
-
* @returns the one-liner, or the form.
|
|
1129
|
-
*/
|
|
1130
|
-
function WebSearchCard(props) {
|
|
1131
|
-
const { t } = props;
|
|
1132
|
-
const state = props.useWebSearchCard((snapshot) => snapshot);
|
|
1133
|
-
if (props.view === "summary") return t("webSearchDescription");
|
|
1134
|
-
const disabled = !state.writable;
|
|
1135
|
-
return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
|
|
1136
|
-
t,
|
|
1137
|
-
state,
|
|
1138
|
-
onSave: props.save,
|
|
1139
|
-
onDiscard: props.discard,
|
|
1140
|
-
children: [
|
|
1141
|
-
(0, react_jsx_runtime.jsx)(SecretField, {
|
|
1142
|
-
id: "plugin-config-web-search-key",
|
|
1143
|
-
label: t("webSearchApiKey"),
|
|
1144
|
-
hint: t("webSearchApiKeyHint"),
|
|
1145
|
-
disabled: !state.apiKeyWritable,
|
|
1146
|
-
text: state.apiKey.text,
|
|
1147
|
-
configured: state.apiKeyConfigured,
|
|
1148
|
-
stateLabel: state.apiKeyConfigured ? t("webSearchApiKeySet") : t("webSearchApiKeyUnset"),
|
|
1149
|
-
onEdit: (text) => {
|
|
1150
|
-
props.edit("apiKey", text);
|
|
1151
|
-
}
|
|
1152
|
-
}),
|
|
1153
|
-
(0, react_jsx_runtime.jsx)(ValueField, {
|
|
1154
|
-
id: "plugin-config-web-search-endpoint",
|
|
1155
|
-
label: t("webSearchBaseUrl"),
|
|
1156
|
-
hint: t("webSearchBaseUrlHint"),
|
|
1157
|
-
overriddenLabel: t("overridden"),
|
|
1158
|
-
resetLabel: t("reset"),
|
|
1159
|
-
invalidLabel: t("invalidNumber"),
|
|
1160
|
-
disabled,
|
|
1161
|
-
...state.baseURL,
|
|
1162
|
-
onEdit: (text) => {
|
|
1163
|
-
props.edit("baseURL", text);
|
|
1164
|
-
},
|
|
1165
|
-
onReset: () => {
|
|
1166
|
-
props.resetField("baseURL");
|
|
1167
|
-
}
|
|
1168
|
-
}),
|
|
1169
|
-
(0, react_jsx_runtime.jsx)(ValueField, {
|
|
1170
|
-
id: "plugin-config-web-search-max-uses",
|
|
1171
|
-
label: t("webSearchMaxUses"),
|
|
1172
|
-
hint: t("webSearchMaxUsesHint"),
|
|
1173
|
-
overriddenLabel: t("overridden"),
|
|
1174
|
-
resetLabel: t("reset"),
|
|
1175
|
-
invalidLabel: t("invalidNumber"),
|
|
1176
|
-
numeric: true,
|
|
1177
|
-
disabled,
|
|
1178
|
-
...state.maxUses,
|
|
1179
|
-
onEdit: (text) => {
|
|
1180
|
-
props.edit("maxUses", text);
|
|
1181
|
-
},
|
|
1182
|
-
onReset: () => {
|
|
1183
|
-
props.resetField("maxUses");
|
|
1184
|
-
}
|
|
1185
|
-
})
|
|
1186
|
-
]
|
|
1187
|
-
});
|
|
1188
|
-
}
|
|
1189
|
-
//#endregion
|
|
1190
|
-
//#region lib/types/client/agent-loop-card-controller.js
|
|
1191
|
-
/** The agent-loop card's staged form over the `agent-loop` settings namespace. */
|
|
1192
|
-
/**
|
|
1193
|
-
* Namespace of the agent loop's user-owned settings. Spelled here rather than
|
|
1194
|
-
* imported: a client package must not depend on a Host package.
|
|
1195
|
-
*/
|
|
1196
|
-
const AGENT_LOOP_NS = "agent-loop";
|
|
1197
|
-
/** Bridges the `agent-loop` scope onto the card's staged form. */
|
|
1198
|
-
var AgentLoopCardController = class {
|
|
1199
|
-
form;
|
|
1200
|
-
store;
|
|
1201
|
-
/** @param scope - the bound settings scope for the `agent-loop` namespace. */
|
|
1202
|
-
constructor(scope) {
|
|
1203
|
-
this.form = new CardForm(scope, [numberField("maxParallelToolCalls")]);
|
|
1204
|
-
this.store = this.form.bind(() => this.projection());
|
|
1205
|
-
}
|
|
1206
|
-
projection() {
|
|
1207
|
-
return {
|
|
1208
|
-
...this.form.shell(),
|
|
1209
|
-
maxParallelToolCalls: this.form.field("maxParallelToolCalls")
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Build the face the card's slot registration injects.
|
|
1214
|
-
* @returns the card's snapshot and its form actions.
|
|
1215
|
-
*/
|
|
1216
|
-
inject() {
|
|
1217
|
-
return {
|
|
1218
|
-
hooks: { agentLoopCard: this.store },
|
|
1219
|
-
...this.form.actions()
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
};
|
|
1223
|
-
//#endregion
|
|
1224
|
-
//#region lib/types/client/bash-card-controller.js
|
|
1225
|
-
/** The shell card's staged form over the `bash` settings namespace. */
|
|
1226
|
-
/**
|
|
1227
|
-
* Namespace of the shell capability. Spelled here rather than imported: a
|
|
1228
|
-
* client package must not depend on a Host package, and the executor families
|
|
1229
|
-
* that own it spell the same value.
|
|
1230
|
-
*/
|
|
1231
|
-
const SHELL_NS = "shell";
|
|
1232
|
-
/** Bridges the `bash` scope onto the shell card's staged form. */
|
|
1233
|
-
var BashCardController = class {
|
|
1234
|
-
form;
|
|
1235
|
-
store;
|
|
1236
|
-
/** @param scope - the bound settings scope for the `bash` namespace. */
|
|
1237
|
-
constructor(scope) {
|
|
1238
|
-
this.form = new CardForm(scope, [numberField("timeoutMs"), numberField("maxOutputBytes")]);
|
|
1239
|
-
this.store = this.form.bind(() => this.projection());
|
|
1240
|
-
}
|
|
1241
|
-
projection() {
|
|
1242
|
-
return {
|
|
1243
|
-
...this.form.shell(),
|
|
1244
|
-
timeoutMs: this.form.field("timeoutMs"),
|
|
1245
|
-
maxOutputBytes: this.form.field("maxOutputBytes")
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
/**
|
|
1249
|
-
* Build the face the card's slot registration injects.
|
|
1250
|
-
* @returns the card's snapshot and its form actions.
|
|
1251
|
-
*/
|
|
1252
|
-
inject() {
|
|
1253
|
-
return {
|
|
1254
|
-
hooks: { bashCard: this.store },
|
|
1255
|
-
...this.form.actions()
|
|
1256
|
-
};
|
|
1257
|
-
}
|
|
1258
|
-
};
|
|
1259
|
-
//#endregion
|
|
1260
|
-
//#region lib/types/client/subagent-model-selection-card-controller.js
|
|
1261
|
-
/** Staged editor for the Host-owned subagent model allowlist. */
|
|
1262
|
-
/** Namespace of the Host-owned subagent model-selection preference. */
|
|
1263
|
-
const SUBAGENT_MODEL_SELECTION_NS = "subagent-model-selection";
|
|
1264
|
-
/**
|
|
1265
|
-
* Stable identity for one exact route; callers resolve it by lookup and never parse it.
|
|
1266
|
-
* @param route - Provider/model route to identify.
|
|
1267
|
-
* @returns Opaque key for lookup within the card.
|
|
1268
|
-
*/
|
|
1269
|
-
function subagentModelKey(route) {
|
|
1270
|
-
return `${route.provider}\0${route.model}`;
|
|
1271
|
-
}
|
|
1272
|
-
/**
|
|
1273
|
-
* Join live adapter metadata with stored routes that remain removable after disappearance.
|
|
1274
|
-
* @param groups - Current model directory grouped by provider.
|
|
1275
|
-
* @param stored - Routes in the effective settings value.
|
|
1276
|
-
* @param selected - Opaque route keys selected in the current draft.
|
|
1277
|
-
* @returns Candidate rows for the card.
|
|
1278
|
-
*/
|
|
1279
|
-
function subagentModelCandidates(groups, stored, selected) {
|
|
1280
|
-
const storedByKey = new Map(stored.map((route) => [subagentModelKey(route), route]));
|
|
1281
|
-
const candidates = groups.flatMap((group) => group.models.map((model) => {
|
|
1282
|
-
const route = {
|
|
1283
|
-
provider: group.id,
|
|
1284
|
-
model: model.id
|
|
1285
|
-
};
|
|
1286
|
-
const key = subagentModelKey(route);
|
|
1287
|
-
storedByKey.delete(key);
|
|
1288
|
-
return {
|
|
1289
|
-
...route,
|
|
1290
|
-
key,
|
|
1291
|
-
providerName: group.name,
|
|
1292
|
-
modelName: model.name,
|
|
1293
|
-
available: true,
|
|
1294
|
-
selected: selected.has(key)
|
|
1295
|
-
};
|
|
1296
|
-
}));
|
|
1297
|
-
for (const route of storedByKey.values()) {
|
|
1298
|
-
const key = subagentModelKey(route);
|
|
1299
|
-
candidates.push({
|
|
1300
|
-
...route,
|
|
1301
|
-
key,
|
|
1302
|
-
providerName: route.provider,
|
|
1303
|
-
modelName: route.model,
|
|
1304
|
-
available: false,
|
|
1305
|
-
selected: selected.has(key)
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
return candidates;
|
|
1309
|
-
}
|
|
1310
|
-
function sameRoutes(left, right) {
|
|
1311
|
-
if (left.length !== right.length) return false;
|
|
1312
|
-
const rightKeys = new Set(right.map(subagentModelKey));
|
|
1313
|
-
return left.every((route) => rightKeys.has(subagentModelKey(route)));
|
|
1314
|
-
}
|
|
1315
|
-
/** Bridges one settings scope and the live adapter directory onto a staged card. */
|
|
1316
|
-
var SubagentModelSelectionCardController = class {
|
|
1317
|
-
scope;
|
|
1318
|
-
ctx;
|
|
1319
|
-
catalogGroups = [];
|
|
1320
|
-
catalogPartial = false;
|
|
1321
|
-
catalogStatus = "idle";
|
|
1322
|
-
draftEnabled;
|
|
1323
|
-
draftRoutes;
|
|
1324
|
-
draftRevision;
|
|
1325
|
-
saving = false;
|
|
1326
|
-
failed = false;
|
|
1327
|
-
conflicted = false;
|
|
1328
|
-
disposed = false;
|
|
1329
|
-
saveGeneration = 0;
|
|
1330
|
-
catalogGeneration = 0;
|
|
1331
|
-
store;
|
|
1332
|
-
unsubscribe;
|
|
1333
|
-
/**
|
|
1334
|
-
* @param scope - bound `subagent-model-selection` settings scope.
|
|
1335
|
-
* @param ctx - the card plugin's context, whose `remote.session` namespace
|
|
1336
|
-
* answers the Host model catalog.
|
|
1337
|
-
*/
|
|
1338
|
-
constructor(scope, ctx) {
|
|
1339
|
-
this.scope = scope;
|
|
1340
|
-
this.ctx = ctx;
|
|
1341
|
-
this.store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(this.projection());
|
|
1342
|
-
this.unsubscribe = scope.subscribe(() => {
|
|
1343
|
-
if (!this.saving && this.draftRoutes !== void 0 && this.scope.getSnapshot().revision !== this.draftRevision) if (this.currentEnabled() === this.enabled() && sameRoutes(this.currentRoutes(), this.desiredRoutes())) this.clearDraft();
|
|
1344
|
-
else this.conflicted = true;
|
|
1345
|
-
if (this.enabled() && this.catalogStatus === "idle") this.loadCatalog();
|
|
1346
|
-
this.publish();
|
|
1347
|
-
});
|
|
1348
|
-
if (this.enabled() && this.catalogStatus === "idle") this.loadCatalog();
|
|
1349
|
-
}
|
|
1350
|
-
/** Stop observing settings and suppress late directory/write settlements. */
|
|
1351
|
-
dispose() {
|
|
1352
|
-
this.disposed = true;
|
|
1353
|
-
this.saveGeneration += 1;
|
|
1354
|
-
this.catalogGeneration += 1;
|
|
1355
|
-
this.unsubscribe();
|
|
1356
|
-
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Build the renderer face for this card.
|
|
1359
|
-
* @returns The snapshot and staged card actions injected into the renderer.
|
|
1360
|
-
*/
|
|
1361
|
-
inject() {
|
|
1362
|
-
return {
|
|
1363
|
-
hooks: { subagentModelSelectionCard: this.store },
|
|
1364
|
-
toggleEnabled: () => {
|
|
1365
|
-
this.toggleEnabled();
|
|
1366
|
-
},
|
|
1367
|
-
toggleModel: (key) => {
|
|
1368
|
-
this.toggleModel(key);
|
|
1369
|
-
},
|
|
1370
|
-
retryCatalog: () => {
|
|
1371
|
-
this.loadCatalog();
|
|
1372
|
-
},
|
|
1373
|
-
save: () => {
|
|
1374
|
-
this.save();
|
|
1375
|
-
},
|
|
1376
|
-
discard: () => {
|
|
1377
|
-
this.discard();
|
|
1378
|
-
}
|
|
1379
|
-
};
|
|
1380
|
-
}
|
|
1381
|
-
currentRoutes() {
|
|
1382
|
-
return this.scope.getSnapshot().value?.allowedModels.map((route) => ({ ...route })) ?? [];
|
|
1383
|
-
}
|
|
1384
|
-
currentEnabled() {
|
|
1385
|
-
return this.scope.getSnapshot().value?.enabled ?? false;
|
|
1386
|
-
}
|
|
1387
|
-
selected() {
|
|
1388
|
-
return new Set(this.draftRoutes?.keys() ?? this.currentRoutes().map(subagentModelKey));
|
|
1389
|
-
}
|
|
1390
|
-
enabled() {
|
|
1391
|
-
return this.draftEnabled ?? this.currentEnabled();
|
|
1392
|
-
}
|
|
1393
|
-
beginDraft() {
|
|
1394
|
-
if (this.draftRoutes === void 0) {
|
|
1395
|
-
const snapshot = this.scope.getSnapshot();
|
|
1396
|
-
this.draftEnabled = snapshot.value?.enabled ?? false;
|
|
1397
|
-
this.draftRoutes = new Map(snapshot.value?.allowedModels.map((route) => [subagentModelKey(route), { ...route }]) ?? []);
|
|
1398
|
-
this.draftRevision = snapshot.revision;
|
|
1399
|
-
}
|
|
1400
|
-
return this.draftRoutes;
|
|
1401
|
-
}
|
|
1402
|
-
toggleEnabled() {
|
|
1403
|
-
const snapshot = this.scope.getSnapshot();
|
|
1404
|
-
if (this.disposed || snapshot.status !== "ready" || !snapshot.writable || this.saving) return;
|
|
1405
|
-
this.beginDraft();
|
|
1406
|
-
this.draftEnabled = !this.draftEnabled;
|
|
1407
|
-
this.failed = false;
|
|
1408
|
-
if (this.draftEnabled && this.catalogStatus === "idle") this.loadCatalog();
|
|
1409
|
-
this.publish();
|
|
1410
|
-
}
|
|
1411
|
-
toggleModel(key) {
|
|
1412
|
-
if (!this.enabled() || this.saving || !this.scope.getSnapshot().writable) return;
|
|
1413
|
-
const candidate = this.candidates().find((candidate) => candidate.key === key);
|
|
1414
|
-
if (candidate === void 0) return;
|
|
1415
|
-
const routes = this.beginDraft();
|
|
1416
|
-
if (routes.has(key)) routes.delete(key);
|
|
1417
|
-
else routes.set(key, {
|
|
1418
|
-
provider: candidate.provider,
|
|
1419
|
-
model: candidate.model
|
|
1420
|
-
});
|
|
1421
|
-
this.failed = false;
|
|
1422
|
-
this.publish();
|
|
1423
|
-
}
|
|
1424
|
-
clearDraft() {
|
|
1425
|
-
this.draftEnabled = void 0;
|
|
1426
|
-
this.draftRoutes = void 0;
|
|
1427
|
-
this.draftRevision = void 0;
|
|
1428
|
-
this.failed = false;
|
|
1429
|
-
this.conflicted = false;
|
|
1430
|
-
}
|
|
1431
|
-
discard() {
|
|
1432
|
-
if (this.saving) return;
|
|
1433
|
-
this.clearDraft();
|
|
1434
|
-
this.publish();
|
|
1435
|
-
}
|
|
1436
|
-
candidates() {
|
|
1437
|
-
const retained = new Map(this.currentRoutes().map((route) => [subagentModelKey(route), route]));
|
|
1438
|
-
for (const [key, route] of this.draftRoutes ?? []) retained.set(key, route);
|
|
1439
|
-
return subagentModelCandidates(this.catalogGroups, [...retained.values()], this.selected());
|
|
1440
|
-
}
|
|
1441
|
-
desiredRoutes() {
|
|
1442
|
-
return [...this.draftRoutes?.values() ?? this.currentRoutes()].map((route) => ({ ...route }));
|
|
1443
|
-
}
|
|
1444
|
-
async save() {
|
|
1445
|
-
const snapshot = this.scope.getSnapshot();
|
|
1446
|
-
const desiredEnabled = this.enabled();
|
|
1447
|
-
const desired = this.desiredRoutes();
|
|
1448
|
-
if (this.disposed || snapshot.status !== "ready" || !snapshot.writable || this.saving || this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired) || desiredEnabled && desired.length === 0) return;
|
|
1449
|
-
if (this.draftRoutes !== void 0 && snapshot.revision !== this.draftRevision) {
|
|
1450
|
-
this.conflicted = true;
|
|
1451
|
-
this.publish();
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
const generation = this.saveGeneration;
|
|
1455
|
-
this.saving = true;
|
|
1456
|
-
this.failed = false;
|
|
1457
|
-
this.conflicted = false;
|
|
1458
|
-
this.publish();
|
|
1459
|
-
await this.scope.mutate([{
|
|
1460
|
-
op: "set",
|
|
1461
|
-
path: ["enabled"],
|
|
1462
|
-
value: desiredEnabled
|
|
1463
|
-
}, {
|
|
1464
|
-
op: "set",
|
|
1465
|
-
path: ["allowedModels"],
|
|
1466
|
-
value: desired.map((route) => ({
|
|
1467
|
-
provider: route.provider,
|
|
1468
|
-
model: route.model
|
|
1469
|
-
}))
|
|
1470
|
-
}], this.draftRevision);
|
|
1471
|
-
if (generation !== this.saveGeneration) return;
|
|
1472
|
-
const landed = this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired);
|
|
1473
|
-
this.saving = false;
|
|
1474
|
-
this.failed = !landed;
|
|
1475
|
-
if (landed) this.clearDraft();
|
|
1476
|
-
this.publish();
|
|
1477
|
-
}
|
|
1478
|
-
/** Invalidate and reload model candidates after a Host model input changes. */
|
|
1479
|
-
refreshCatalog() {
|
|
1480
|
-
if (this.disposed) return;
|
|
1481
|
-
this.catalogGeneration += 1;
|
|
1482
|
-
this.catalogStatus = "idle";
|
|
1483
|
-
this.catalogPartial = false;
|
|
1484
|
-
if (this.enabled()) this.loadCatalog();
|
|
1485
|
-
else this.publish();
|
|
1486
|
-
}
|
|
1487
|
-
/** Drop Host-specific candidates and drafts, then reload after reconnecting. */
|
|
1488
|
-
resetConnection() {
|
|
1489
|
-
if (this.disposed) return;
|
|
1490
|
-
this.saveGeneration += 1;
|
|
1491
|
-
this.saving = false;
|
|
1492
|
-
this.clearDraft();
|
|
1493
|
-
this.catalogGroups = [];
|
|
1494
|
-
this.refreshCatalog();
|
|
1495
|
-
}
|
|
1496
|
-
async loadCatalog() {
|
|
1497
|
-
if (this.disposed || this.catalogStatus === "loading") return;
|
|
1498
|
-
const generation = this.catalogGeneration;
|
|
1499
|
-
this.catalogStatus = "loading";
|
|
1500
|
-
this.catalogPartial = false;
|
|
1501
|
-
this.publish();
|
|
1502
|
-
const response = await this.ctx.remote.session.modelCatalog();
|
|
1503
|
-
if (generation !== this.catalogGeneration) return;
|
|
1504
|
-
if (response.ok) {
|
|
1505
|
-
this.catalogGroups = response.value.groups;
|
|
1506
|
-
this.catalogPartial = response.value.failures.length > 0;
|
|
1507
|
-
this.catalogStatus = "ready";
|
|
1508
|
-
} else this.catalogStatus = "error";
|
|
1509
|
-
this.publish();
|
|
1510
|
-
}
|
|
1511
|
-
projection() {
|
|
1512
|
-
const snapshot = this.scope.getSnapshot();
|
|
1513
|
-
const current = this.currentRoutes();
|
|
1514
|
-
const desired = this.desiredRoutes();
|
|
1515
|
-
const enabled = this.enabled();
|
|
1516
|
-
return {
|
|
1517
|
-
available: snapshot.status === "ready",
|
|
1518
|
-
writable: snapshot.writable,
|
|
1519
|
-
dirty: this.currentEnabled() !== enabled || !sameRoutes(current, desired),
|
|
1520
|
-
invalid: enabled && desired.length === 0,
|
|
1521
|
-
saving: this.saving,
|
|
1522
|
-
failed: this.failed,
|
|
1523
|
-
enabled,
|
|
1524
|
-
candidates: this.candidates(),
|
|
1525
|
-
catalogStatus: this.catalogStatus,
|
|
1526
|
-
catalogPartial: this.catalogPartial,
|
|
1527
|
-
conflicted: this.conflicted
|
|
1528
|
-
};
|
|
1529
|
-
}
|
|
1530
|
-
publish() {
|
|
1531
|
-
this.store.set(this.projection());
|
|
1532
|
-
}
|
|
1533
|
-
};
|
|
1534
|
-
//#endregion
|
|
1535
|
-
//#region lib/types/client/web-search-card-controller.js
|
|
1536
|
-
/**
|
|
1537
|
-
* The web-search card's staged form over the `web-search-deepseek` settings
|
|
1538
|
-
* namespace.
|
|
1539
|
-
*
|
|
1540
|
-
* The key is the one control that does not live in the section: its literal
|
|
1541
|
-
* never rides a response, so the card learns only whether one is configured
|
|
1542
|
-
* and writes it through the credentials domain, addressed by the reference the
|
|
1543
|
-
* section names. It is still staged with the rest of the form, so one save
|
|
1544
|
-
* covers everything the card shows.
|
|
1545
|
-
*/
|
|
1546
|
-
/**
|
|
1547
|
-
* Namespace of the DeepSeek search provider. Spelled here rather than
|
|
1548
|
-
* imported: a client package must not depend on a Host package.
|
|
1549
|
-
*/
|
|
1550
|
-
const WEB_SEARCH_NS = "web-search-deepseek";
|
|
1551
|
-
/** Credential reference the provider resolves when the section names none. */
|
|
1552
|
-
const DEFAULT_API_KEY_REF = "DEEPSEEK_API_KEY";
|
|
1553
|
-
/** Form field the credential control stages under. */
|
|
1554
|
-
const API_KEY_FIELD = "apiKey";
|
|
1555
|
-
/** Bridges the `web-search-deepseek` scope and the credentials domain onto the card. */
|
|
1556
|
-
var WebSearchCardController = class {
|
|
1557
|
-
scope;
|
|
1558
|
-
ctx;
|
|
1559
|
-
form;
|
|
1560
|
-
store;
|
|
1561
|
-
credential = {
|
|
1562
|
-
ref: "",
|
|
1563
|
-
configured: false,
|
|
1564
|
-
writable: true
|
|
1565
|
-
};
|
|
1566
|
-
/**
|
|
1567
|
-
* @param scope - the bound settings scope for the `web-search-deepseek` namespace.
|
|
1568
|
-
* @param ctx - the card plugin's context, whose `remote.credentials` namespace
|
|
1569
|
-
* answers for the credential the section references.
|
|
1570
|
-
*/
|
|
1571
|
-
constructor(scope, ctx) {
|
|
1572
|
-
this.scope = scope;
|
|
1573
|
-
this.ctx = ctx;
|
|
1574
|
-
this.form = new CardForm(scope, [textField("baseURL"), numberField("maxUses")], [{
|
|
1575
|
-
field: API_KEY_FIELD,
|
|
1576
|
-
write: (text) => this.writeKey(text)
|
|
1577
|
-
}]);
|
|
1578
|
-
this.store = this.form.bind(() => this.projection());
|
|
1579
|
-
scope.subscribe(() => {
|
|
1580
|
-
this.readCredential();
|
|
1581
|
-
});
|
|
1582
|
-
this.readCredential();
|
|
1583
|
-
}
|
|
1584
|
-
projection() {
|
|
1585
|
-
return {
|
|
1586
|
-
...this.form.shell(),
|
|
1587
|
-
baseURL: this.form.field("baseURL"),
|
|
1588
|
-
maxUses: this.form.field("maxUses"),
|
|
1589
|
-
apiKey: this.form.field(API_KEY_FIELD),
|
|
1590
|
-
apiKeyConfigured: this.credential.configured,
|
|
1591
|
-
apiKeyWritable: this.credential.writable
|
|
1592
|
-
};
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* Ask the credentials domain about the reference the section currently names.
|
|
1596
|
-
*
|
|
1597
|
-
* The answer is stored with the reference it describes: `apiKeyEnv` can
|
|
1598
|
-
* change between the request and its response, and two reads can settle out
|
|
1599
|
-
* of order, so a response is published only while it still answers for the
|
|
1600
|
-
* reference in force.
|
|
1601
|
-
*/
|
|
1602
|
-
async readCredential() {
|
|
1603
|
-
const ref = refOf(this.scope.getSnapshot());
|
|
1604
|
-
if (ref !== this.credential.ref) {
|
|
1605
|
-
this.credential = {
|
|
1606
|
-
ref,
|
|
1607
|
-
configured: false,
|
|
1608
|
-
writable: true
|
|
1609
|
-
};
|
|
1610
|
-
this.store.set(this.projection());
|
|
1611
|
-
}
|
|
1612
|
-
const response = await this.ctx.remote.credentials.describe([ref]);
|
|
1613
|
-
if (!response.ok || ref !== refOf(this.scope.getSnapshot())) return;
|
|
1614
|
-
const view = response.value[ref];
|
|
1615
|
-
const next = {
|
|
1616
|
-
ref,
|
|
1617
|
-
configured: view?.configured ?? false,
|
|
1618
|
-
writable: view?.writable ?? true
|
|
1619
|
-
};
|
|
1620
|
-
if (next.configured === this.credential.configured && next.writable === this.credential.writable) return;
|
|
1621
|
-
this.credential = next;
|
|
1622
|
-
this.store.set(this.projection());
|
|
1623
|
-
}
|
|
1624
|
-
/**
|
|
1625
|
-
* Re-read after the Host reports a change to the reference this card watches.
|
|
1626
|
-
*
|
|
1627
|
-
* A key can be written from somewhere else — the Models page addresses the
|
|
1628
|
-
* same reference — and the settings section does not change when it is, so
|
|
1629
|
-
* without this the badge keeps reporting a state the Host already replaced.
|
|
1630
|
-
* @param ref - the reference the Host reports as changed.
|
|
1631
|
-
*/
|
|
1632
|
-
refreshCredential(ref) {
|
|
1633
|
-
if (ref !== this.credential.ref) return;
|
|
1634
|
-
this.readCredential();
|
|
1635
|
-
}
|
|
1636
|
-
/**
|
|
1637
|
-
* Build the face the card's slot registration injects.
|
|
1638
|
-
* @returns the card's snapshot and its form actions.
|
|
1639
|
-
*/
|
|
1640
|
-
inject() {
|
|
1641
|
-
return {
|
|
1642
|
-
hooks: { webSearchCard: this.store },
|
|
1643
|
-
...this.form.actions()
|
|
1644
|
-
};
|
|
1645
|
-
}
|
|
1646
|
-
/**
|
|
1647
|
-
* Write the staged key, then re-read whether the Host now holds one.
|
|
1648
|
-
* @param value - the staged credential literal.
|
|
1649
|
-
* @returns whether the Host reports a configured credential afterwards.
|
|
1650
|
-
*/
|
|
1651
|
-
async writeKey(value) {
|
|
1652
|
-
await this.ctx.remote.credentials.set(refOf(this.scope.getSnapshot()), value);
|
|
1653
|
-
await this.readCredential();
|
|
1654
|
-
return this.credential.configured;
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
|
-
/**
|
|
1658
|
-
* The credential reference the section names, or the provider's default.
|
|
1659
|
-
* @param snapshot - the current scope snapshot.
|
|
1660
|
-
* @returns the reference to address.
|
|
1661
|
-
*/
|
|
1662
|
-
function refOf(snapshot) {
|
|
1663
|
-
const declared = snapshot.value?.apiKeyEnv;
|
|
1664
|
-
return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_API_KEY_REF;
|
|
1665
|
-
}
|
|
1666
|
-
//#endregion
|
|
1667
131
|
//#region lib/types/client/locales.js
|
|
1668
|
-
/** Locale bundles for the built-in plugins settings section
|
|
132
|
+
/** Locale bundles for the built-in plugins settings section. */
|
|
1669
133
|
/** English copy. */
|
|
1670
134
|
const en = {
|
|
1671
135
|
nav: "Built-in plugins",
|
|
1672
136
|
title: "Built-in plugins",
|
|
1673
137
|
intro: "Inspect the plugins this deployment ships.",
|
|
1674
138
|
tabs: "Plugin views",
|
|
1675
|
-
empty: "This deployment exposes no plugin views."
|
|
1676
|
-
overridden: "Overridden",
|
|
1677
|
-
reset: "Reset to default",
|
|
1678
|
-
readOnly: "This deployment stores settings read-only.",
|
|
1679
|
-
unavailable: "This plugin is not loaded, so it cannot be configured right now.",
|
|
1680
|
-
save: "Save",
|
|
1681
|
-
saving: "Saving…",
|
|
1682
|
-
saveFailed: "The deployment did not accept these values; they were left for you to correct.",
|
|
1683
|
-
invalidNumber: "Enter a number, or leave blank to use the default.",
|
|
1684
|
-
bashTitle: "Shell",
|
|
1685
|
-
bashDescription: "Limits every command the agent runs.",
|
|
1686
|
-
bashTimeoutMs: "Command timeout (ms)",
|
|
1687
|
-
bashTimeoutMsHint: "How long one command may run before it is terminated.",
|
|
1688
|
-
bashMaxOutputBytes: "Output cap per stream (bytes)",
|
|
1689
|
-
bashMaxOutputBytesHint: "Output beyond this spills to a temporary file rather than being lost.",
|
|
1690
|
-
agentLoopTitle: "Agent loop",
|
|
1691
|
-
agentLoopDescription: "How the agent dispatches tool calls.",
|
|
1692
|
-
agentLoopMaxParallel: "Parallel tool calls",
|
|
1693
|
-
agentLoopMaxParallelHint: "Upper bound on parallel-safe calls running at once within one step.",
|
|
1694
|
-
webSearchTitle: "Web search",
|
|
1695
|
-
webSearchDescription: "The DeepSeek search provider.",
|
|
1696
|
-
webSearchApiKey: "API key",
|
|
1697
|
-
webSearchApiKeyHint: "Stored outside the settings file. Leave blank to keep the current key.",
|
|
1698
|
-
webSearchApiKeySet: "A key is configured.",
|
|
1699
|
-
webSearchApiKeyUnset: "No key is configured; search is unavailable until one is.",
|
|
1700
|
-
webSearchBaseUrl: "Endpoint",
|
|
1701
|
-
webSearchBaseUrlHint: "Leave blank to use the provider default.",
|
|
1702
|
-
webSearchMaxUses: "Max searches per request",
|
|
1703
|
-
webSearchMaxUsesHint: "How many times one request may search before it must answer.",
|
|
1704
|
-
subagentTitle: "Subagent",
|
|
1705
|
-
subagentDescription: "Set Subagent recursion depth, count, and models.",
|
|
1706
|
-
subagentLimitsTitle: "Limits",
|
|
1707
|
-
subagentMaxDepth: "Maximum recursion depth",
|
|
1708
|
-
subagentDepthHelpLabel: "About maximum recursion depth",
|
|
1709
|
-
subagentDepthHelp: "Limits how many levels of Subagents an Agent can create.",
|
|
1710
|
-
subagentDepthZero: "Disable Subagents",
|
|
1711
|
-
subagentDepthOne: "Only the main Agent can create Subagents",
|
|
1712
|
-
subagentDepthOverride: "If a tool defines its own maximum recursion depth, that setting takes precedence.",
|
|
1713
|
-
subagentMaxActive: "Subagent parallelism limit",
|
|
1714
|
-
subagentCapacityHelpLabel: "About the Subagent parallelism limit",
|
|
1715
|
-
subagentCapacityHelp: "Total live Subagents under the same main Agent, across all recursion levels. The main Agent is excluded. New start requests are rejected when the limit is reached.",
|
|
1716
|
-
subagentDepthInvalid: "Enter a whole number of 0 or more.",
|
|
1717
|
-
subagentCapacityInvalid: "Enter a whole number of 1 or more.",
|
|
1718
|
-
subagentModelSelectionTitle: "Model selection",
|
|
1719
|
-
subagentModelSelectionToggle: "Allow agents to choose models for Subagents",
|
|
1720
|
-
subagentModelSelectionChoose: "When enabled, agents can choose a provider, model, and reasoning effort for each Subagent from the authorized models below. Applies only to new sessions.",
|
|
1721
|
-
subagentModelSelectionAllowed: "Models agents may choose",
|
|
1722
|
-
subagentModelSelectionLoading: "Loading models…",
|
|
1723
|
-
subagentModelSelectionLoadFailed: "Models could not be loaded.",
|
|
1724
|
-
subagentModelSelectionRetry: "Retry",
|
|
1725
|
-
subagentModelSelectionPartial: "Some model providers could not be loaded; saved choices remain removable.",
|
|
1726
|
-
subagentModelSelectionUnavailable: "Currently unavailable",
|
|
1727
|
-
subagentModelSelectionUnavailableGroup: "Saved but currently unavailable",
|
|
1728
|
-
subagentModelSelectionEmpty: "No model provider currently advertises a model.",
|
|
1729
|
-
subagentModelSelectionRequired: "Select at least one model before saving.",
|
|
1730
|
-
subagentModelSelectionConflict: "Settings changed elsewhere. Discard your draft and try again.",
|
|
1731
|
-
subagentModelSelectionOff: "Subagents use configured defaults or inherit the parent agent's model. Saved model choices are retained."
|
|
139
|
+
empty: "This deployment exposes no plugin views."
|
|
1732
140
|
};
|
|
1733
141
|
/** Simplified Chinese copy. */
|
|
1734
142
|
const zh = {
|
|
@@ -1736,89 +144,24 @@ window.__ModuleLoader__.load({
|
|
|
1736
144
|
title: "内置插件",
|
|
1737
145
|
intro: "查看内置部署的插件列表",
|
|
1738
146
|
tabs: "插件视图",
|
|
1739
|
-
empty: "本部署没有开放任何插件视图。"
|
|
1740
|
-
overridden: "已覆盖",
|
|
1741
|
-
reset: "恢复默认",
|
|
1742
|
-
readOnly: "本部署的设置为只读。",
|
|
1743
|
-
unavailable: "该插件当前未加载,暂时无法配置。",
|
|
1744
|
-
save: "保存",
|
|
1745
|
-
saving: "保存中…",
|
|
1746
|
-
saveFailed: "本部署没有接受这些值,已保留供你修改。",
|
|
1747
|
-
invalidNumber: "请填数字;留空表示使用默认值。",
|
|
1748
|
-
bashTitle: "终端",
|
|
1749
|
-
bashDescription: "限制 agent 运行的每一条命令。",
|
|
1750
|
-
bashTimeoutMs: "命令超时(毫秒)",
|
|
1751
|
-
bashTimeoutMsHint: "单条命令允许运行多久,超时即终止。",
|
|
1752
|
-
bashMaxOutputBytes: "单流输出上限(字节)",
|
|
1753
|
-
bashMaxOutputBytesHint: "超出部分会转存到临时文件,而不是被丢弃。",
|
|
1754
|
-
agentLoopTitle: "Agent 循环",
|
|
1755
|
-
agentLoopDescription: "Agent 如何派发工具调用。",
|
|
1756
|
-
agentLoopMaxParallel: "并行工具调用数",
|
|
1757
|
-
agentLoopMaxParallelHint: "同一步内最多同时运行多少个可并行的调用。",
|
|
1758
|
-
webSearchTitle: "网页搜索",
|
|
1759
|
-
webSearchDescription: "DeepSeek 搜索提供方。",
|
|
1760
|
-
webSearchApiKey: "API Key",
|
|
1761
|
-
webSearchApiKeyHint: "不写入设置文件。留空表示保持当前密钥。",
|
|
1762
|
-
webSearchApiKeySet: "已配置密钥。",
|
|
1763
|
-
webSearchApiKeyUnset: "未配置密钥;配置之前搜索不可用。",
|
|
1764
|
-
webSearchBaseUrl: "接口地址",
|
|
1765
|
-
webSearchBaseUrlHint: "留空则使用提供方默认地址。",
|
|
1766
|
-
webSearchMaxUses: "单次请求最多搜索次数",
|
|
1767
|
-
webSearchMaxUsesHint: "一次请求在必须作答前最多可以搜索多少次。",
|
|
1768
|
-
subagentTitle: "Subagent",
|
|
1769
|
-
subagentDescription: "设置 Subagent 的递归层级、数量和模型。",
|
|
1770
|
-
subagentLimitsTitle: "运行限制",
|
|
1771
|
-
subagentMaxDepth: "最大递归深度",
|
|
1772
|
-
subagentDepthHelpLabel: "最大递归深度说明",
|
|
1773
|
-
subagentDepthHelp: "限制 Agent 创建 Subagent 的递归层级。",
|
|
1774
|
-
subagentDepthZero: "禁用 Subagent",
|
|
1775
|
-
subagentDepthOne: "仅允许主 Agent 创建 Subagent",
|
|
1776
|
-
subagentDepthOverride: "如果某个工具单独设置了最大递归深度,以该工具的设置为准。",
|
|
1777
|
-
subagentMaxActive: "Subagent 并行数量上限",
|
|
1778
|
-
subagentCapacityHelpLabel: "Subagent 并行数量上限说明",
|
|
1779
|
-
subagentCapacityHelp: "同一主 Agent 下,所有递归层级同时存活的 Subagent 总数,主 Agent 不计入。达到上限时,新的启动请求会被拒绝。",
|
|
1780
|
-
subagentDepthInvalid: "请输入不小于 0 的整数。",
|
|
1781
|
-
subagentCapacityInvalid: "请输入不小于 1 的整数。",
|
|
1782
|
-
subagentModelSelectionTitle: "模型选择",
|
|
1783
|
-
subagentModelSelectionToggle: "允许 Agent 为 Subagent 选择模型",
|
|
1784
|
-
subagentModelSelectionChoose: "开启后,Agent 可以从下方授权模型中,为每个 Subagent 选择提供方、模型和推理强度。仅影响新会话。",
|
|
1785
|
-
subagentModelSelectionAllowed: "Agent 可选择的模型",
|
|
1786
|
-
subagentModelSelectionLoading: "正在加载模型…",
|
|
1787
|
-
subagentModelSelectionLoadFailed: "无法加载模型。",
|
|
1788
|
-
subagentModelSelectionRetry: "重试",
|
|
1789
|
-
subagentModelSelectionPartial: "部分模型提供方暂时无法加载;已保存的选择仍可移除。",
|
|
1790
|
-
subagentModelSelectionUnavailable: "当前不可用",
|
|
1791
|
-
subagentModelSelectionUnavailableGroup: "已保存但当前不可用",
|
|
1792
|
-
subagentModelSelectionEmpty: "当前没有模型提供方公布模型。",
|
|
1793
|
-
subagentModelSelectionRequired: "保存前请至少选择一个模型。",
|
|
1794
|
-
subagentModelSelectionConflict: "设置已在其他位置更新。请放弃修改后重试。",
|
|
1795
|
-
subagentModelSelectionOff: "关闭后,Subagent 使用配置的默认模型或继承父 Agent 的模型;已选模型会保留。"
|
|
147
|
+
empty: "本部署没有开放任何插件视图。"
|
|
1796
148
|
};
|
|
1797
149
|
//#endregion
|
|
1798
150
|
//#region lib/types/client/index.js
|
|
1799
151
|
/**
|
|
1800
|
-
* Built-in plugins settings
|
|
1801
|
-
* pages, browser half. The Settings section is the shell around the
|
|
152
|
+
* Built-in plugins settings section, browser half: the shell around the
|
|
1802
153
|
* feature-owned tabs registered into `settings.plugins.tab` (the read-only
|
|
1803
|
-
* inventory ships one)
|
|
1804
|
-
*
|
|
1805
|
-
*
|
|
1806
|
-
*
|
|
1807
|
-
* pages unaware of one another and of the section.
|
|
154
|
+
* inventory ships one). The configuration pages of the host-plane plugins
|
|
155
|
+
* live in their own companion packages, which register into the Plugins
|
|
156
|
+
* page; this section owns the Settings navigation entry and the tab chrome
|
|
157
|
+
* only.
|
|
1808
158
|
*/
|
|
1809
159
|
/** Dictionary namespace owned by this plugin. */
|
|
1810
160
|
const NS = "settings.plugins";
|
|
1811
161
|
/** Required services (cordis fiber inject). */
|
|
1812
|
-
const inject = [
|
|
1813
|
-
"slots",
|
|
1814
|
-
"locale",
|
|
1815
|
-
"remote",
|
|
1816
|
-
"remote.credentials",
|
|
1817
|
-
"remote.session",
|
|
1818
|
-
"settingsScope"
|
|
1819
|
-
];
|
|
162
|
+
const inject = ["slots", "locale"];
|
|
1820
163
|
/**
|
|
1821
|
-
* Mount the built-in plugins section
|
|
164
|
+
* Mount the built-in plugins section.
|
|
1822
165
|
* @param ctx - the browser plugin context.
|
|
1823
166
|
*/
|
|
1824
167
|
function apply(ctx) {
|
|
@@ -1827,87 +170,6 @@ window.__ModuleLoader__.load({
|
|
|
1827
170
|
zh,
|
|
1828
171
|
en
|
|
1829
172
|
}), "ui-settings-plugins: section dictionaries");
|
|
1830
|
-
const bash = new BashCardController(ctx.settingsScope.bind({ namespace: SHELL_NS }));
|
|
1831
|
-
const agentLoop = new AgentLoopCardController(ctx.settingsScope.bind({ namespace: AGENT_LOOP_NS }));
|
|
1832
|
-
const webSearch = new WebSearchCardController(ctx.settingsScope.bind({ namespace: WEB_SEARCH_NS }), ctx);
|
|
1833
|
-
const subagentLimits = new SubagentLimitsCardController(ctx.settingsScope.bind({ namespace: "subagent" }));
|
|
1834
|
-
const subagentModelSelection = new SubagentModelSelectionCardController(ctx.settingsScope.bind({ namespace: SUBAGENT_MODEL_SELECTION_NS }), ctx);
|
|
1835
|
-
const subagentLimitsFace = subagentLimits.inject();
|
|
1836
|
-
const subagentModelsFace = subagentModelSelection.inject();
|
|
1837
|
-
ctx.effect(() => ctx.remote.$on("credentials/reference-updated", (ref) => {
|
|
1838
|
-
webSearch.refreshCredential(ref);
|
|
1839
|
-
}), "ui-settings-plugins: credential invalidations");
|
|
1840
|
-
ctx.effect(() => ctx.remote.$on("llm/adapters-updated", () => {
|
|
1841
|
-
subagentModelSelection.refreshCatalog();
|
|
1842
|
-
}), "ui-settings-plugins: subagent adapter invalidations");
|
|
1843
|
-
ctx.effect(() => ctx.remote.$on("settings/document-updated", () => {
|
|
1844
|
-
subagentModelSelection.refreshCatalog();
|
|
1845
|
-
}), "ui-settings-plugins: subagent settings invalidations");
|
|
1846
|
-
ctx.effect(() => ctx.on("connection/reset", () => {
|
|
1847
|
-
subagentModelSelection.resetConnection();
|
|
1848
|
-
}), "ui-settings-plugins: subagent connection generation");
|
|
1849
|
-
ctx.effect(() => () => {
|
|
1850
|
-
subagentModelSelection.dispose();
|
|
1851
|
-
}, "ui-settings-plugins: subagent preference");
|
|
1852
|
-
const pages = [
|
|
1853
|
-
[[SHELL_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
|
|
1854
|
-
name: "plugins.item",
|
|
1855
|
-
id: "bash",
|
|
1856
|
-
order: 10,
|
|
1857
|
-
label: () => t("bashTitle"),
|
|
1858
|
-
locale: NS,
|
|
1859
|
-
inject: () => bash.inject()
|
|
1860
|
-
}, BashCard))],
|
|
1861
|
-
[[AGENT_LOOP_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
|
|
1862
|
-
name: "plugins.item",
|
|
1863
|
-
id: "agent-loop",
|
|
1864
|
-
order: 20,
|
|
1865
|
-
label: () => t("agentLoopTitle"),
|
|
1866
|
-
locale: NS,
|
|
1867
|
-
inject: () => agentLoop.inject()
|
|
1868
|
-
}, AgentLoopCard))],
|
|
1869
|
-
[["subagent", SUBAGENT_MODEL_SELECTION_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
|
|
1870
|
-
name: "plugins.item",
|
|
1871
|
-
id: "subagent",
|
|
1872
|
-
order: 30,
|
|
1873
|
-
label: () => t("subagentTitle"),
|
|
1874
|
-
locale: NS,
|
|
1875
|
-
inject: () => subagentCardFace(subagentLimitsFace, subagentModelsFace)
|
|
1876
|
-
}, SubagentCard))],
|
|
1877
|
-
[[WEB_SEARCH_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
|
|
1878
|
-
name: "plugins.item",
|
|
1879
|
-
id: "web-search",
|
|
1880
|
-
order: 40,
|
|
1881
|
-
label: () => t("webSearchTitle"),
|
|
1882
|
-
locale: NS,
|
|
1883
|
-
inject: () => webSearch.inject()
|
|
1884
|
-
}, WebSearchCard))]
|
|
1885
|
-
];
|
|
1886
|
-
const describeFace = ctx.settingsScope.describe();
|
|
1887
|
-
ctx.effect(() => {
|
|
1888
|
-
const registered = /* @__PURE__ */ new Map();
|
|
1889
|
-
const sync = () => {
|
|
1890
|
-
const served = new Set(describeFace.getSnapshot().view?.namespaces.map((view) => view.ns) ?? []);
|
|
1891
|
-
for (const [namespaces, register] of pages) {
|
|
1892
|
-
const namespace = namespaces[0];
|
|
1893
|
-
const available = namespaces.some((namespace) => served.has(namespace));
|
|
1894
|
-
const off = registered.get(namespace);
|
|
1895
|
-
if (available && off === void 0) registered.set(namespace, register());
|
|
1896
|
-
else if (!available && off !== void 0) {
|
|
1897
|
-
off();
|
|
1898
|
-
registered.delete(namespace);
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
};
|
|
1902
|
-
const unsubscribe = describeFace.subscribe(sync);
|
|
1903
|
-
describeFace.ensure();
|
|
1904
|
-
sync();
|
|
1905
|
-
return () => {
|
|
1906
|
-
unsubscribe();
|
|
1907
|
-
for (const off of registered.values()) off();
|
|
1908
|
-
registered.clear();
|
|
1909
|
-
};
|
|
1910
|
-
}, "ui-settings-plugins: configuration pages");
|
|
1911
173
|
let tabsVersion = -1;
|
|
1912
174
|
let tabsRevision = -1;
|
|
1913
175
|
let tabs = [];
|