@qilin-agent/client-ui-settings-plugins 0.0.0-stage → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js ADDED
@@ -0,0 +1,1749 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@qilin-agent/client-ui-settings-plugins",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let _qilin_agent_client_ui_slots = require("@qilin-agent/client-ui-slots");
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
+ let _qilin_agent_client_ui_primitives = require("@qilin-agent/client-ui-primitives");
10
+ let react = require("react");
11
+ let _qilin_agent_client_store = require("@qilin-agent/client-store");
12
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-plugins/src/client/PluginConfigForm.module.css.mjs
13
+ const css$4 = ".PuF0xa_form{flex-direction:column;display:flex}.PuF0xa_readOnly,.PuF0xa_unavailable{color:var(--qilin-alias-label-tertiary);margin:0 0 12px;font-size:12px;line-height:1.5}.PuF0xa_footer{align-items:center;gap:8px;padding-top:16px;display:flex}.PuF0xa_failed{min-width:0;color:var(--qilin-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.PuF0xa_save{appearance:none;font:inherit;cursor:pointer;background:var(--qilin-alias-label-primary);color:var(--qilin-alias-bg-layer-3);border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.PuF0xa_save:disabled{opacity:.4;cursor:default}.PuF0xa_save:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:1px}";
14
+ const tagId$4 = "@qilin-agent/client-ui-settings-plugins/PluginConfigForm.module.css";
15
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
16
+ const tag = document.createElement("style");
17
+ tag.dataset.plugin = "@qilin-agent/client-ui-settings-plugins";
18
+ tag.dataset.pluginCss = tagId$4;
19
+ tag.textContent = css$4;
20
+ document.head.appendChild(tag);
21
+ }
22
+ var PluginConfigForm_module_css_default = {
23
+ "failed": "PuF0xa_failed",
24
+ "footer": "PuF0xa_footer",
25
+ "form": "PuF0xa_form",
26
+ "readOnly": "PuF0xa_readOnly",
27
+ "save": "PuF0xa_save",
28
+ "unavailable": "PuF0xa_unavailable"
29
+ };
30
+ //#endregion
31
+ //#region lib/types/client/PluginConfigForm.js
32
+ /**
33
+ * One plugin's configuration form as its page on the Plugins page shows it:
34
+ * the read-only notice when the deployment stores settings read-only, the
35
+ * plugin's controls, and the save that writes every staged edit. The page
36
+ * draws the plugin's title and one-liner itself.
37
+ *
38
+ * Only a save writes. Leaving the page drops every staged edit, so the form
39
+ * discards on unmount and offers no discard control. A form whose namespace
40
+ * the Host stopped serving says so in place of its controls rather than
41
+ * showing fields nothing would accept.
42
+ */
43
+ /**
44
+ * Render one plugin's configuration form.
45
+ * @param props - the form state, its controls, and the save and discard actions.
46
+ * @returns the form, or the unavailable line while the namespace is not served.
47
+ */
48
+ function PluginConfigForm(props) {
49
+ const { state } = props;
50
+ const discard = (0, react.useRef)(props.onDiscard);
51
+ discard.current = props.onDiscard;
52
+ (0, react.useEffect)(() => () => {
53
+ discard.current();
54
+ }, []);
55
+ if (!state.available) return (0, react_jsx_runtime.jsx)("p", {
56
+ className: PluginConfigForm_module_css_default.unavailable,
57
+ role: "status",
58
+ children: props.t("unavailable")
59
+ });
60
+ const blocked = !state.dirty || state.invalid || state.saving;
61
+ return (0, react_jsx_runtime.jsxs)("div", {
62
+ className: PluginConfigForm_module_css_default.form,
63
+ children: [
64
+ !state.writable ? (0, react_jsx_runtime.jsx)("p", {
65
+ className: PluginConfigForm_module_css_default.readOnly,
66
+ role: "status",
67
+ children: props.t("readOnly")
68
+ }) : null,
69
+ props.children,
70
+ (0, react_jsx_runtime.jsxs)("div", {
71
+ className: PluginConfigForm_module_css_default.footer,
72
+ children: [state.failed ? (0, react_jsx_runtime.jsx)("p", {
73
+ className: PluginConfigForm_module_css_default.failed,
74
+ role: "status",
75
+ children: props.t("saveFailed")
76
+ }) : null, (0, react_jsx_runtime.jsx)("button", {
77
+ type: "button",
78
+ className: PluginConfigForm_module_css_default.save,
79
+ disabled: blocked,
80
+ onClick: props.onSave,
81
+ children: props.t(state.saving ? "saving" : "save")
82
+ })]
83
+ })
84
+ ]
85
+ });
86
+ }
87
+ //#endregion
88
+ //#region lib/types/client/AgentLoopCard.js
89
+ /**
90
+ * Render the agent loop's one-liner or its configuration form, as the Plugins page asks.
91
+ * @param props - the view asked for, locale copy, the form snapshot, and its actions.
92
+ * @returns the one-liner, or the form.
93
+ */
94
+ function AgentLoopCard(props) {
95
+ const { t } = props;
96
+ const state = props.useAgentLoopCard((snapshot) => snapshot);
97
+ if (props.view === "summary") return t("agentLoopDescription");
98
+ return (0, react_jsx_runtime.jsx)(PluginConfigForm, {
99
+ t,
100
+ state,
101
+ onSave: props.save,
102
+ onDiscard: props.discard,
103
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
104
+ id: "plugin-config-agent-loop-parallel",
105
+ label: t("agentLoopMaxParallel"),
106
+ hint: t("agentLoopMaxParallelHint"),
107
+ overriddenLabel: t("overridden"),
108
+ resetLabel: t("reset"),
109
+ invalidLabel: t("invalidNumber"),
110
+ numeric: true,
111
+ disabled: !state.writable,
112
+ ...state.maxParallelToolCalls,
113
+ onEdit: (text) => {
114
+ props.edit("maxParallelToolCalls", text);
115
+ },
116
+ onReset: () => {
117
+ props.resetField("maxParallelToolCalls");
118
+ }
119
+ })
120
+ });
121
+ }
122
+ //#endregion
123
+ //#region lib/types/client/BashCard.js
124
+ /**
125
+ * Render the shell plugin's one-liner or its configuration form, as the Plugins page asks.
126
+ * @param props - the view asked for, locale copy, the form snapshot, and its actions.
127
+ * @returns the one-liner, or the form.
128
+ */
129
+ function BashCard(props) {
130
+ const { t } = props;
131
+ const state = props.useBashCard((snapshot) => snapshot);
132
+ if (props.view === "summary") return t("bashDescription");
133
+ const disabled = !state.writable;
134
+ return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
135
+ t,
136
+ state,
137
+ onSave: props.save,
138
+ onDiscard: props.discard,
139
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
140
+ id: "plugin-config-bash-timeout",
141
+ label: t("bashTimeoutMs"),
142
+ hint: t("bashTimeoutMsHint"),
143
+ overriddenLabel: t("overridden"),
144
+ resetLabel: t("reset"),
145
+ invalidLabel: t("invalidNumber"),
146
+ numeric: true,
147
+ disabled,
148
+ ...state.timeoutMs,
149
+ onEdit: (text) => {
150
+ props.edit("timeoutMs", text);
151
+ },
152
+ onReset: () => {
153
+ props.resetField("timeoutMs");
154
+ }
155
+ }), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
156
+ id: "plugin-config-bash-output",
157
+ label: t("bashMaxOutputBytes"),
158
+ hint: t("bashMaxOutputBytesHint"),
159
+ overriddenLabel: t("overridden"),
160
+ resetLabel: t("reset"),
161
+ invalidLabel: t("invalidNumber"),
162
+ numeric: true,
163
+ disabled,
164
+ ...state.maxOutputBytes,
165
+ onEdit: (text) => {
166
+ props.edit("maxOutputBytes", text);
167
+ },
168
+ onReset: () => {
169
+ props.resetField("maxOutputBytes");
170
+ }
171
+ })]
172
+ });
173
+ }
174
+ //#endregion
175
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-plugins/src/client/PluginsSettingsSection.module.css.mjs
176
+ const css$3 = "._2gTzQa_section{color:var(--qilin-alias-label-primary);flex-direction:column;gap:12px;display:flex}._2gTzQa_heading{margin:0;font-size:18px;font-weight:600}._2gTzQa_intro{color:var(--qilin-alias-label-tertiary);margin:0;font-size:13px}._2gTzQa_tabs{border-bottom:.5px solid var(--qilin-alias-border-l2);align-items:flex-end;gap:22px;margin-top:2px;display:flex}._2gTzQa_tab{color:var(--qilin-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;padding:7px 1px 9px;font-size:13px;line-height:20px;position:relative}._2gTzQa_tab:hover,._2gTzQa_tab[data-active=true]{color:var(--qilin-alias-label-primary)}._2gTzQa_tab[data-active=true]:after,._2gTzQa_tab:focus-visible:after{background:var(--qilin-alias-label-primary);content:\"\";border-radius:2px 2px 0 0;height:2px;position:absolute;bottom:-1px;left:0;right:0}._2gTzQa_tab:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:2px;color:var(--qilin-alias-label-primary);border-radius:2px}._2gTzQa_panel{min-width:0;padding-top:2px}._2gTzQa_cards{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}._2gTzQa_empty{color:var(--qilin-alias-label-tertiary);margin:0;font-size:13px}._2gTzQa_configurable{flex-direction:column;gap:10px;display:flex}._2gTzQa_presetSettings{flex-direction:column;gap:8px;display:flex}._2gTzQa_presetSettingsTitle{margin:0;font-size:15px;font-weight:600;line-height:22px}";
177
+ const tagId$3 = "@qilin-agent/client-ui-settings-plugins/PluginsSettingsSection.module.css";
178
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
179
+ const tag = document.createElement("style");
180
+ tag.dataset.plugin = "@qilin-agent/client-ui-settings-plugins";
181
+ tag.dataset.pluginCss = tagId$3;
182
+ tag.textContent = css$3;
183
+ document.head.appendChild(tag);
184
+ }
185
+ var PluginsSettingsSection_module_css_default = {
186
+ "cards": "_2gTzQa_cards",
187
+ "configurable": "_2gTzQa_configurable",
188
+ "empty": "_2gTzQa_empty",
189
+ "heading": "_2gTzQa_heading",
190
+ "intro": "_2gTzQa_intro",
191
+ "panel": "_2gTzQa_panel",
192
+ "presetSettings": "_2gTzQa_presetSettings",
193
+ "presetSettingsTitle": "_2gTzQa_presetSettingsTitle",
194
+ "section": "_2gTzQa_section",
195
+ "tab": "_2gTzQa_tab",
196
+ "tabs": "_2gTzQa_tabs"
197
+ };
198
+ //#endregion
199
+ //#region lib/types/client/PluginsSettingsSection.js
200
+ /** Plugins settings section: localized tabs around feature-owned pages. */
201
+ /** Render one Plugins page whose contents arrive from feature-owned tabs; one contribution shows as the page itself. */
202
+ function PluginsSettingsSection({ t, renderSlot, useTabs }) {
203
+ const tabsId = (0, react.useId)();
204
+ const tabRefs = (0, react.useRef)([]);
205
+ const rows = useTabs((value) => value);
206
+ const [activeId, setActiveId] = (0, react.useState)();
207
+ const [visitedIds, setVisitedIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
208
+ const active = rows.find((row) => row.id === activeId)?.id ?? rows[0]?.id;
209
+ const single = rows.length === 1 ? rows[0] : void 0;
210
+ (0, react.useEffect)(() => {
211
+ if (active === void 0) return;
212
+ setVisitedIds((previous) => {
213
+ if (previous.has(active)) return previous;
214
+ return new Set([...previous, active]);
215
+ });
216
+ }, [active]);
217
+ return (0, react_jsx_runtime.jsxs)("div", {
218
+ className: PluginsSettingsSection_module_css_default.section,
219
+ children: [
220
+ (0, react_jsx_runtime.jsx)("h2", {
221
+ className: PluginsSettingsSection_module_css_default.heading,
222
+ children: t("title")
223
+ }),
224
+ (0, react_jsx_runtime.jsx)("p", {
225
+ className: PluginsSettingsSection_module_css_default.intro,
226
+ children: t("intro")
227
+ }),
228
+ rows.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
229
+ className: PluginsSettingsSection_module_css_default.empty,
230
+ children: t("empty")
231
+ }) : single !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
232
+ className: PluginsSettingsSection_module_css_default.panel,
233
+ children: renderSlot("settings.plugins.tab", {}, { only: single.id })
234
+ }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
235
+ className: PluginsSettingsSection_module_css_default.tabs,
236
+ role: "tablist",
237
+ "aria-label": t("tabs"),
238
+ children: rows.map((row, index) => {
239
+ const selected = row.id === active;
240
+ return (0, react_jsx_runtime.jsx)("button", {
241
+ ref: (element) => {
242
+ tabRefs.current[index] = element;
243
+ },
244
+ id: `${tabsId}-tab-${row.id}`,
245
+ type: "button",
246
+ role: "tab",
247
+ className: PluginsSettingsSection_module_css_default.tab,
248
+ "aria-selected": selected,
249
+ "aria-controls": `${tabsId}-panel-${row.id}`,
250
+ "data-active": selected ? "true" : void 0,
251
+ tabIndex: selected ? 0 : -1,
252
+ onClick: () => {
253
+ setActiveId(row.id);
254
+ },
255
+ onKeyDown: (event) => {
256
+ let nextIndex;
257
+ switch (event.key) {
258
+ case "ArrowRight":
259
+ nextIndex = (index + 1) % rows.length;
260
+ break;
261
+ case "ArrowLeft":
262
+ nextIndex = (index - 1 + rows.length) % rows.length;
263
+ break;
264
+ case "Home":
265
+ nextIndex = 0;
266
+ break;
267
+ case "End":
268
+ nextIndex = rows.length - 1;
269
+ break;
270
+ default: return;
271
+ }
272
+ event.preventDefault();
273
+ const nextRow = rows[nextIndex];
274
+ const nextTab = tabRefs.current[nextIndex];
275
+ setActiveId(nextRow.id);
276
+ nextTab.focus();
277
+ },
278
+ children: row.label
279
+ }, row.id);
280
+ })
281
+ }), rows.filter((row) => row.id === active || visitedIds.has(row.id)).map((row) => {
282
+ const selected = row.id === active;
283
+ return (0, react_jsx_runtime.jsx)("div", {
284
+ id: `${tabsId}-panel-${row.id}`,
285
+ className: PluginsSettingsSection_module_css_default.panel,
286
+ role: "tabpanel",
287
+ "aria-labelledby": `${tabsId}-tab-${row.id}`,
288
+ hidden: !selected,
289
+ children: renderSlot("settings.plugins.tab", {}, { only: row.id })
290
+ }, row.id);
291
+ })] })
292
+ ]
293
+ });
294
+ }
295
+ //#endregion
296
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-plugins/src/client/SubagentLimitsFields.module.css.mjs
297
+ const css$2 = ".ilBR6W_limits{grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:16px;display:grid}.ilBR6W_limit{min-width:0}.ilBR6W_limit input{font-variant-numeric:tabular-nums;min-width:0}.ilBR6W_depthTable{border-collapse:collapse;border-block:.5px solid var(--qilin-alias-border-l2);width:100%;font:inherit;text-align:left;margin:8px 0}.ilBR6W_depthTable th,.ilBR6W_depthTable td{vertical-align:top;padding:6px 0}.ilBR6W_depthTable th{font-variant-numeric:tabular-nums;width:24px;color:var(--qilin-alias-label-primary);padding-right:8px;font-weight:500}.ilBR6W_depthTable tr+tr{border-top:.5px solid var(--qilin-alias-border-l2)}";
298
+ const tagId$2 = "@qilin-agent/client-ui-settings-plugins/SubagentLimitsFields.module.css";
299
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
300
+ const tag = document.createElement("style");
301
+ tag.dataset.plugin = "@qilin-agent/client-ui-settings-plugins";
302
+ tag.dataset.pluginCss = tagId$2;
303
+ tag.textContent = css$2;
304
+ document.head.appendChild(tag);
305
+ }
306
+ var SubagentLimitsFields_module_css_default = {
307
+ "depthTable": "ilBR6W_depthTable",
308
+ "limit": "ilBR6W_limit",
309
+ "limits": "ilBR6W_limits"
310
+ };
311
+ //#endregion
312
+ //#region lib/types/client/SubagentLimitsFields.js
313
+ /**
314
+ * Render the depth and capacity fields with their original validation and reset behavior.
315
+ * @param props - Locale, staged fields, and edit callbacks.
316
+ * @returns Two responsive fields and their application rules.
317
+ */
318
+ function SubagentLimitsFields(props) {
319
+ const { t, state } = props;
320
+ return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
321
+ className: SubagentLimitsFields_module_css_default.limits,
322
+ children: [(0, react_jsx_runtime.jsx)("div", {
323
+ className: SubagentLimitsFields_module_css_default.limit,
324
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
325
+ id: "plugin-config-subagent-depth",
326
+ label: t("subagentMaxDepth"),
327
+ help: {
328
+ label: t("subagentDepthHelpLabel"),
329
+ content: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
330
+ (0, react_jsx_runtime.jsx)("p", { children: t("subagentDepthHelp") }),
331
+ (0, react_jsx_runtime.jsx)("table", {
332
+ className: SubagentLimitsFields_module_css_default.depthTable,
333
+ "aria-label": t("subagentDepthHelpLabel"),
334
+ children: (0, react_jsx_runtime.jsxs)("tbody", { children: [(0, react_jsx_runtime.jsxs)("tr", { children: [(0, react_jsx_runtime.jsx)("th", {
335
+ scope: "row",
336
+ children: 0
337
+ }), (0, react_jsx_runtime.jsx)("td", { children: t("subagentDepthZero") })] }), (0, react_jsx_runtime.jsxs)("tr", { children: [(0, react_jsx_runtime.jsx)("th", {
338
+ scope: "row",
339
+ children: 1
340
+ }), (0, react_jsx_runtime.jsx)("td", { children: t("subagentDepthOne") })] })] })
341
+ }),
342
+ (0, react_jsx_runtime.jsx)("p", { children: t("subagentDepthOverride") })
343
+ ] })
344
+ },
345
+ overriddenLabel: t("overridden"),
346
+ resetLabel: t("reset"),
347
+ invalidLabel: t("subagentDepthInvalid"),
348
+ numeric: true,
349
+ disabled: !state.writable || state.saving,
350
+ ...state.maxDepth,
351
+ onEdit: (text) => {
352
+ props.edit("maxDepth", text);
353
+ },
354
+ onReset: () => {
355
+ props.resetField("maxDepth");
356
+ }
357
+ })
358
+ }), (0, react_jsx_runtime.jsx)("div", {
359
+ className: SubagentLimitsFields_module_css_default.limit,
360
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
361
+ id: "plugin-config-subagent-capacity",
362
+ label: t("subagentMaxActive"),
363
+ help: {
364
+ label: t("subagentCapacityHelpLabel"),
365
+ content: (0, react_jsx_runtime.jsx)("p", { children: t("subagentCapacityHelp") })
366
+ },
367
+ overriddenLabel: t("overridden"),
368
+ resetLabel: t("reset"),
369
+ invalidLabel: t("subagentCapacityInvalid"),
370
+ numeric: true,
371
+ disabled: !state.writable || state.saving,
372
+ ...state.maxActiveSubagents,
373
+ onEdit: (text) => {
374
+ props.edit("maxActiveSubagents", text);
375
+ },
376
+ onReset: () => {
377
+ props.resetField("maxActiveSubagents");
378
+ }
379
+ })
380
+ })]
381
+ }) });
382
+ }
383
+ //#endregion
384
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-plugins/src/client/SubagentModelSelectionFields.module.css.mjs
385
+ const css$1 = ".USzyAq_permission{gap:6px;padding:12px 0;display:grid}.USzyAq_toggleRow{color:var(--qilin-alias-label-primary);justify-content:space-between;align-items:flex-start;gap:16px;font-size:13px;line-height:1.5;display:flex}.USzyAq_toggleLabel{flex:1;min-width:0}.USzyAq_selection{gap:10px;display:grid}.USzyAq_hint,.USzyAq_notice,.USzyAq_invalid,.USzyAq_conflict{margin:0;font-size:12px;line-height:1.5}.USzyAq_hint,.USzyAq_notice{color:var(--qilin-alias-label-tertiary)}.USzyAq_invalid,.USzyAq_conflict{color:var(--qilin-alias-state-error-primary)}.USzyAq_catalogError{color:var(--qilin-alias-state-error-primary);justify-content:space-between;align-items:center;gap:12px;font-size:12px;display:flex}.USzyAq_catalogError button{color:var(--qilin-alias-brand-primary);cursor:pointer;background:0 0;border:0;padding:0}.USzyAq_models{border:.5px solid var(--qilin-alias-border-l4);border-radius:8px;gap:6px;min-width:0;max-height:280px;margin:0;padding:10px;display:grid;overflow:auto}.USzyAq_models legend{color:var(--qilin-alias-label-secondary);padding:0 4px;font-size:12px}.USzyAq_modelGroup{gap:6px;display:grid}.USzyAq_modelGroup+.USzyAq_modelGroup{border-top:.5px solid var(--qilin-alias-border-l3);margin-top:4px;padding-top:10px}.USzyAq_providerName{color:var(--qilin-alias-label-tertiary);padding:0 6px;font-size:11px;font-weight:500}.USzyAq_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}.USzyAq_model:hover{background:var(--qilin-alias-bg-layer-4)}.USzyAq_modelName,.USzyAq_route{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.USzyAq_modelName{color:var(--qilin-alias-label-primary);font-size:13px}.USzyAq_route{color:var(--qilin-alias-label-tertiary);margin-top:2px;font-size:11px}.USzyAq_unavailable{color:var(--qilin-alias-label-tertiary);font-size:11px}";
386
+ const tagId$1 = "@qilin-agent/client-ui-settings-plugins/SubagentModelSelectionFields.module.css";
387
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
388
+ const tag = document.createElement("style");
389
+ tag.dataset.plugin = "@qilin-agent/client-ui-settings-plugins";
390
+ tag.dataset.pluginCss = tagId$1;
391
+ tag.textContent = css$1;
392
+ document.head.appendChild(tag);
393
+ }
394
+ var SubagentModelSelectionFields_module_css_default = {
395
+ "catalogError": "USzyAq_catalogError",
396
+ "conflict": "USzyAq_conflict",
397
+ "hint": "USzyAq_hint",
398
+ "invalid": "USzyAq_invalid",
399
+ "model": "USzyAq_model",
400
+ "modelGroup": "USzyAq_modelGroup",
401
+ "modelName": "USzyAq_modelName",
402
+ "models": "USzyAq_models",
403
+ "notice": "USzyAq_notice",
404
+ "permission": "USzyAq_permission",
405
+ "providerName": "USzyAq_providerName",
406
+ "route": "USzyAq_route",
407
+ "selection": "USzyAq_selection",
408
+ "toggleLabel": "USzyAq_toggleLabel",
409
+ "toggleRow": "USzyAq_toggleRow",
410
+ "unavailable": "USzyAq_unavailable"
411
+ };
412
+ //#endregion
413
+ //#region lib/types/client/SubagentModelSelectionFields.js
414
+ /** User control for model-selectable subagent delegation in new sessions. */
415
+ /**
416
+ * Render the default-off preference and its exact adapter-route choices.
417
+ * @param props - locale copy, the card snapshot, and its toggle action.
418
+ * @returns the model permission and route choices inside the shared card.
419
+ */
420
+ function SubagentModelSelectionFields(props) {
421
+ const { t, state } = props;
422
+ const availableGroups = /* @__PURE__ */ new Map();
423
+ const unavailable = [];
424
+ for (const candidate of state.candidates) {
425
+ if (!candidate.available) {
426
+ unavailable.push(candidate);
427
+ continue;
428
+ }
429
+ const group = availableGroups.get(candidate.provider);
430
+ if (group === void 0) availableGroups.set(candidate.provider, {
431
+ providerName: candidate.providerName,
432
+ candidates: [candidate]
433
+ });
434
+ else group.candidates.push(candidate);
435
+ }
436
+ const renderCandidate = (candidate) => (0, react_jsx_runtime.jsxs)("label", {
437
+ className: SubagentModelSelectionFields_module_css_default.model,
438
+ children: [
439
+ (0, react_jsx_runtime.jsx)("input", {
440
+ type: "checkbox",
441
+ checked: candidate.selected,
442
+ disabled: !state.writable || state.saving,
443
+ onChange: () => {
444
+ props.toggleModel(candidate.key);
445
+ }
446
+ }),
447
+ (0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("span", {
448
+ className: SubagentModelSelectionFields_module_css_default.modelName,
449
+ children: candidate.modelName
450
+ }), (0, react_jsx_runtime.jsx)("span", {
451
+ className: SubagentModelSelectionFields_module_css_default.route,
452
+ children: `${candidate.providerName} · ${candidate.provider}/${candidate.model}`
453
+ })] }),
454
+ !candidate.available ? (0, react_jsx_runtime.jsx)("span", {
455
+ className: SubagentModelSelectionFields_module_css_default.unavailable,
456
+ children: t("subagentModelSelectionUnavailable")
457
+ }) : null
458
+ ]
459
+ }, candidate.key);
460
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
461
+ (0, react_jsx_runtime.jsxs)("div", {
462
+ className: SubagentModelSelectionFields_module_css_default.permission,
463
+ children: [(0, react_jsx_runtime.jsxs)("div", {
464
+ className: SubagentModelSelectionFields_module_css_default.toggleRow,
465
+ children: [(0, react_jsx_runtime.jsx)("span", {
466
+ className: SubagentModelSelectionFields_module_css_default.toggleLabel,
467
+ children: t("subagentModelSelectionToggle")
468
+ }), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Switch, {
469
+ checked: state.enabled,
470
+ label: t("subagentModelSelectionToggle"),
471
+ disabled: !state.writable || state.saving,
472
+ onChange: props.toggleEnabled
473
+ })]
474
+ }), (0, react_jsx_runtime.jsx)("p", {
475
+ className: SubagentModelSelectionFields_module_css_default.hint,
476
+ children: t(state.enabled ? "subagentModelSelectionChoose" : "subagentModelSelectionOff")
477
+ })]
478
+ }),
479
+ state.enabled ? (0, react_jsx_runtime.jsxs)("div", {
480
+ className: SubagentModelSelectionFields_module_css_default.selection,
481
+ children: [
482
+ state.catalogStatus === "loading" ? (0, react_jsx_runtime.jsx)("p", {
483
+ className: SubagentModelSelectionFields_module_css_default.notice,
484
+ role: "status",
485
+ children: t("subagentModelSelectionLoading")
486
+ }) : null,
487
+ state.catalogStatus === "error" ? (0, react_jsx_runtime.jsxs)("div", {
488
+ className: SubagentModelSelectionFields_module_css_default.catalogError,
489
+ role: "alert",
490
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("subagentModelSelectionLoadFailed") }), (0, react_jsx_runtime.jsx)("button", {
491
+ type: "button",
492
+ disabled: state.saving,
493
+ onClick: props.retryCatalog,
494
+ children: t("subagentModelSelectionRetry")
495
+ })]
496
+ }) : null,
497
+ state.catalogPartial ? (0, react_jsx_runtime.jsx)("p", {
498
+ className: SubagentModelSelectionFields_module_css_default.notice,
499
+ children: t("subagentModelSelectionPartial")
500
+ }) : null,
501
+ state.candidates.length > 0 ? (0, react_jsx_runtime.jsxs)("fieldset", {
502
+ className: SubagentModelSelectionFields_module_css_default.models,
503
+ children: [
504
+ (0, react_jsx_runtime.jsx)("legend", { children: t("subagentModelSelectionAllowed") }),
505
+ [...availableGroups].map(([provider, group]) => (0, react_jsx_runtime.jsxs)("div", {
506
+ className: SubagentModelSelectionFields_module_css_default.modelGroup,
507
+ children: [(0, react_jsx_runtime.jsx)("div", {
508
+ className: SubagentModelSelectionFields_module_css_default.providerName,
509
+ children: group.providerName
510
+ }), group.candidates.map(renderCandidate)]
511
+ }, provider)),
512
+ unavailable.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
513
+ className: SubagentModelSelectionFields_module_css_default.modelGroup,
514
+ children: [(0, react_jsx_runtime.jsx)("div", {
515
+ className: SubagentModelSelectionFields_module_css_default.providerName,
516
+ children: t("subagentModelSelectionUnavailableGroup")
517
+ }), unavailable.map(renderCandidate)]
518
+ }) : null
519
+ ]
520
+ }) : state.catalogStatus === "ready" ? (0, react_jsx_runtime.jsx)("p", {
521
+ className: SubagentModelSelectionFields_module_css_default.notice,
522
+ children: t("subagentModelSelectionEmpty")
523
+ }) : null,
524
+ state.invalid ? (0, react_jsx_runtime.jsx)("p", {
525
+ className: SubagentModelSelectionFields_module_css_default.invalid,
526
+ children: t("subagentModelSelectionRequired")
527
+ }) : null
528
+ ]
529
+ }) : null,
530
+ state.conflicted ? (0, react_jsx_runtime.jsx)("p", {
531
+ className: SubagentModelSelectionFields_module_css_default.conflict,
532
+ role: "status",
533
+ children: t("subagentModelSelectionConflict")
534
+ }) : null
535
+ ] });
536
+ }
537
+ //#endregion
538
+ //#region lib/types/client/subagent-card-controller.js
539
+ /** Shared presentation and actions for the two Host-owned Subagent settings sections. */
540
+ /**
541
+ * Derive the shared card state without duplicating either form's subscriptions.
542
+ * @param limits - Current delegation-limit form.
543
+ * @param models - Current model-authorization form.
544
+ * @returns Availability and settlement across the sections this Host serves.
545
+ */
546
+ function subagentCardShell(limits, models) {
547
+ const sections = [limits, models].filter((section) => section.available);
548
+ return {
549
+ available: sections.length > 0,
550
+ writable: sections.every((section) => section.writable),
551
+ dirty: sections.some((section) => section.dirty),
552
+ invalid: sections.some((section) => section.invalid) || models.available && models.dirty && models.conflicted,
553
+ saving: sections.some((section) => section.saving),
554
+ failed: sections.some((section) => section.failed)
555
+ };
556
+ }
557
+ /**
558
+ * Compose one card from the existing forms; each write retains its namespace revision fence.
559
+ * @param limits - Limit form source and actions.
560
+ * @param models - Model form source and actions.
561
+ * @returns Framework-bound sources and shared save/discard actions.
562
+ */
563
+ function subagentCardFace(limits, models) {
564
+ return {
565
+ hooks: {
566
+ ...limits.hooks,
567
+ ...models.hooks
568
+ },
569
+ editLimit: limits.edit,
570
+ resetLimit: limits.resetField,
571
+ toggleEnabled: models.toggleEnabled,
572
+ toggleModel: models.toggleModel,
573
+ retryCatalog: models.retryCatalog,
574
+ save: () => {
575
+ const limitState = limits.hooks.subagentLimitsCard.getSnapshot();
576
+ const modelState = models.hooks.subagentModelSelectionCard.getSnapshot();
577
+ const state = subagentCardShell(limitState, modelState);
578
+ if (!state.available || !state.writable || !state.dirty || state.invalid || state.saving) return;
579
+ if (modelState.available && modelState.dirty) models.save();
580
+ if (limitState.available && limitState.dirty) limits.save();
581
+ },
582
+ discard: () => {
583
+ if (subagentCardShell(limits.hooks.subagentLimitsCard.getSnapshot(), models.hooks.subagentModelSelectionCard.getSnapshot()).saving) return;
584
+ limits.discard();
585
+ models.discard();
586
+ }
587
+ };
588
+ }
589
+ //#endregion
590
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-plugins/src/client/SubagentCard.module.css.mjs
591
+ const css = ".NLp0wG_section{min-width:0;padding:16px 0}.NLp0wG_heading{color:var(--qilin-alias-label-primary);margin:0;font-size:13px;font-weight:600;line-height:1.5}";
592
+ const tagId = "@qilin-agent/client-ui-settings-plugins/SubagentCard.module.css";
593
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
594
+ const tag = document.createElement("style");
595
+ tag.dataset.plugin = "@qilin-agent/client-ui-settings-plugins";
596
+ tag.dataset.pluginCss = tagId;
597
+ tag.textContent = css;
598
+ document.head.appendChild(tag);
599
+ }
600
+ var SubagentCard_module_css_default = {
601
+ "heading": "NLp0wG_heading",
602
+ "section": "NLp0wG_section"
603
+ };
604
+ //#endregion
605
+ //#region lib/types/client/SubagentCard.js
606
+ /** One settings card for Subagent delegation limits and model authorization. */
607
+ /**
608
+ * Render the available Subagent settings with one configuration page and save footer.
609
+ * @param props - Locale, both form snapshots, and their shared actions.
610
+ * @returns The summary or the available settings form.
611
+ */
612
+ function SubagentCard(props) {
613
+ const { t } = props;
614
+ const limits = props.useSubagentLimitsCard((snapshot) => snapshot);
615
+ const models = props.useSubagentModelSelectionCard((snapshot) => snapshot);
616
+ const headingId = (0, react.useId)();
617
+ if (props.view === "summary") return t("subagentDescription");
618
+ const state = subagentCardShell(limits, models);
619
+ return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
620
+ t,
621
+ state,
622
+ onSave: props.save,
623
+ onDiscard: props.discard,
624
+ children: [limits.available ? (0, react_jsx_runtime.jsxs)("section", {
625
+ className: SubagentCard_module_css_default.section,
626
+ "aria-labelledby": `${headingId}-limits`,
627
+ children: [(0, react_jsx_runtime.jsx)("h3", {
628
+ className: SubagentCard_module_css_default.heading,
629
+ id: `${headingId}-limits`,
630
+ children: t("subagentLimitsTitle")
631
+ }), (0, react_jsx_runtime.jsx)(SubagentLimitsFields, {
632
+ t,
633
+ state: {
634
+ ...limits,
635
+ saving: state.saving
636
+ },
637
+ edit: props.editLimit,
638
+ resetField: props.resetLimit
639
+ })]
640
+ }) : null, models.available ? (0, react_jsx_runtime.jsxs)("section", {
641
+ className: SubagentCard_module_css_default.section,
642
+ "aria-labelledby": `${headingId}-models`,
643
+ children: [(0, react_jsx_runtime.jsx)("h3", {
644
+ className: SubagentCard_module_css_default.heading,
645
+ id: `${headingId}-models`,
646
+ children: t("subagentModelSelectionTitle")
647
+ }), (0, react_jsx_runtime.jsx)(SubagentModelSelectionFields, {
648
+ t,
649
+ state: {
650
+ ...models,
651
+ saving: state.saving
652
+ },
653
+ toggleEnabled: props.toggleEnabled,
654
+ toggleModel: props.toggleModel,
655
+ retryCatalog: props.retryCatalog
656
+ })]
657
+ }) : null]
658
+ });
659
+ }
660
+ //#endregion
661
+ //#region lib/types/client/subagent-limits-card-controller.js
662
+ /** Staged delegation limits backed by the Host's subagent settings section. */
663
+ function limitField(field, minimum) {
664
+ const numeric = (0, _qilin_agent_client_ui_primitives.settingsNumberField)(field);
665
+ return {
666
+ ...numeric,
667
+ parse: (text) => {
668
+ const write = numeric.parse(text);
669
+ if (write?.kind !== "set") return write;
670
+ const value = write.value;
671
+ return Number.isSafeInteger(value) && value >= minimum && !Object.is(value, -0) ? write : void 0;
672
+ }
673
+ };
674
+ }
675
+ /** Bind two independently resettable limits to one staged settings form. */
676
+ var SubagentLimitsCardController = class {
677
+ form;
678
+ store;
679
+ /** @param scope - The Host's `subagent` settings section. */
680
+ constructor(scope) {
681
+ this.form = new _qilin_agent_client_ui_primitives.SettingsFormModel(scope, [limitField("maxDepth", 0), limitField("maxActiveSubagents", 1)]);
682
+ this.store = this.form.bind(() => ({
683
+ ...this.form.shell(),
684
+ maxDepth: this.form.field("maxDepth"),
685
+ maxActiveSubagents: this.form.field("maxActiveSubagents")
686
+ }));
687
+ }
688
+ /**
689
+ * Bind the limits editor to the slot renderer.
690
+ * @returns The limits snapshot and staged write actions.
691
+ */
692
+ inject() {
693
+ return {
694
+ hooks: { subagentLimitsCard: this.store },
695
+ ...this.form.actions()
696
+ };
697
+ }
698
+ };
699
+ //#endregion
700
+ //#region lib/types/client/GitCard.js
701
+ /**
702
+ * Render the Git plugin's one-liner or its configuration form, as the Plugins page asks.
703
+ * @param props - the view asked for, locale copy, the form snapshot, and its actions.
704
+ * @returns the one-liner, or the form.
705
+ */
706
+ function GitCard(props) {
707
+ const { t } = props;
708
+ const state = props.useGitCard((snapshot) => snapshot);
709
+ if (props.view === "summary") return t("gitDescription");
710
+ const disabled = !state.writable;
711
+ const shared = {
712
+ overriddenLabel: t("overridden"),
713
+ resetLabel: t("reset"),
714
+ invalidLabel: t("invalidNumber"),
715
+ disabled
716
+ };
717
+ return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
718
+ t,
719
+ state,
720
+ onSave: props.save,
721
+ onDiscard: props.discard,
722
+ children: [
723
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
724
+ id: "plugin-config-git-bin",
725
+ label: t("gitBin"),
726
+ hint: t("gitBinHint"),
727
+ ...shared,
728
+ ...state.gitBin,
729
+ onEdit: (text) => {
730
+ props.edit("gitBin", text);
731
+ },
732
+ onReset: () => {
733
+ props.resetField("gitBin");
734
+ }
735
+ }),
736
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
737
+ id: "plugin-config-gh-bin",
738
+ label: t("ghBin"),
739
+ hint: t("ghBinHint"),
740
+ ...shared,
741
+ ...state.ghBin,
742
+ onEdit: (text) => {
743
+ props.edit("ghBin", text);
744
+ },
745
+ onReset: () => {
746
+ props.resetField("ghBin");
747
+ }
748
+ }),
749
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
750
+ id: "plugin-config-git-timeout",
751
+ label: t("gitTimeoutMs"),
752
+ hint: t("gitTimeoutMsHint"),
753
+ numeric: true,
754
+ ...shared,
755
+ ...state.timeoutMs,
756
+ onEdit: (text) => {
757
+ props.edit("timeoutMs", text);
758
+ },
759
+ onReset: () => {
760
+ props.resetField("timeoutMs");
761
+ }
762
+ }),
763
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
764
+ id: "plugin-config-git-discovery-timeout",
765
+ label: t("gitDiscoveryTimeoutMs"),
766
+ hint: t("gitDiscoveryTimeoutMsHint"),
767
+ numeric: true,
768
+ ...shared,
769
+ ...state.discoveryTimeoutMs,
770
+ onEdit: (text) => {
771
+ props.edit("discoveryTimeoutMs", text);
772
+ },
773
+ onReset: () => {
774
+ props.resetField("discoveryTimeoutMs");
775
+ }
776
+ }),
777
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
778
+ id: "plugin-config-gh-timeout",
779
+ label: t("ghTimeoutMs"),
780
+ hint: t("ghTimeoutMsHint"),
781
+ numeric: true,
782
+ ...shared,
783
+ ...state.ghTimeoutMs,
784
+ onEdit: (text) => {
785
+ props.edit("ghTimeoutMs", text);
786
+ },
787
+ onReset: () => {
788
+ props.resetField("ghTimeoutMs");
789
+ }
790
+ }),
791
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
792
+ id: "plugin-config-git-max-diff",
793
+ label: t("gitMaxDiffBytes"),
794
+ hint: t("gitMaxDiffBytesHint"),
795
+ numeric: true,
796
+ ...shared,
797
+ ...state.maxDiffBytes,
798
+ onEdit: (text) => {
799
+ props.edit("maxDiffBytes", text);
800
+ },
801
+ onReset: () => {
802
+ props.resetField("maxDiffBytes");
803
+ }
804
+ }),
805
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
806
+ id: "plugin-config-git-max-stderr",
807
+ label: t("gitMaxStderrChars"),
808
+ hint: t("gitMaxStderrCharsHint"),
809
+ numeric: true,
810
+ ...shared,
811
+ ...state.maxStderrChars,
812
+ onEdit: (text) => {
813
+ props.edit("maxStderrChars", text);
814
+ },
815
+ onReset: () => {
816
+ props.resetField("maxStderrChars");
817
+ }
818
+ }),
819
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
820
+ id: "plugin-config-git-max-list",
821
+ label: t("gitMaxListEntries"),
822
+ hint: t("gitMaxListEntriesHint"),
823
+ numeric: true,
824
+ ...shared,
825
+ ...state.maxListEntries,
826
+ onEdit: (text) => {
827
+ props.edit("maxListEntries", text);
828
+ },
829
+ onReset: () => {
830
+ props.resetField("maxListEntries");
831
+ }
832
+ })
833
+ ]
834
+ });
835
+ }
836
+ //#endregion
837
+ //#region lib/types/client/WebSearchCard.js
838
+ /**
839
+ * Render the web-search provider's one-liner or its configuration form, as the Plugins page asks.
840
+ * @param props - the view asked for, locale copy, the form snapshot, and its actions.
841
+ * @returns the one-liner, or the form.
842
+ */
843
+ function WebSearchCard(props) {
844
+ const { t } = props;
845
+ const state = props.useWebSearchCard((snapshot) => snapshot);
846
+ if (props.view === "summary") return t("webSearchDescription");
847
+ const disabled = !state.writable;
848
+ return (0, react_jsx_runtime.jsxs)(PluginConfigForm, {
849
+ t,
850
+ state,
851
+ onSave: props.save,
852
+ onDiscard: props.discard,
853
+ children: [
854
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsSecretField, {
855
+ id: "plugin-config-web-search-key",
856
+ label: t("webSearchApiKey"),
857
+ hint: t("webSearchApiKeyHint"),
858
+ disabled: !state.apiKeyWritable,
859
+ text: state.apiKey.text,
860
+ configured: state.apiKeyConfigured,
861
+ stateLabel: state.apiKeyConfigured ? t("webSearchApiKeySet") : t("webSearchApiKeyUnset"),
862
+ onEdit: (text) => {
863
+ props.edit("apiKey", text);
864
+ }
865
+ }),
866
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
867
+ id: "plugin-config-web-search-endpoint",
868
+ label: t("webSearchBaseUrl"),
869
+ hint: t("webSearchBaseUrlHint"),
870
+ overriddenLabel: t("overridden"),
871
+ resetLabel: t("reset"),
872
+ invalidLabel: t("invalidNumber"),
873
+ disabled,
874
+ ...state.baseURL,
875
+ onEdit: (text) => {
876
+ props.edit("baseURL", text);
877
+ },
878
+ onReset: () => {
879
+ props.resetField("baseURL");
880
+ }
881
+ }),
882
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.SettingsValueField, {
883
+ id: "plugin-config-web-search-max-uses",
884
+ label: t("webSearchMaxUses"),
885
+ hint: t("webSearchMaxUsesHint"),
886
+ overriddenLabel: t("overridden"),
887
+ resetLabel: t("reset"),
888
+ invalidLabel: t("invalidNumber"),
889
+ numeric: true,
890
+ disabled,
891
+ ...state.maxUses,
892
+ onEdit: (text) => {
893
+ props.edit("maxUses", text);
894
+ },
895
+ onReset: () => {
896
+ props.resetField("maxUses");
897
+ }
898
+ })
899
+ ]
900
+ });
901
+ }
902
+ //#endregion
903
+ //#region lib/types/client/agent-loop-card-controller.js
904
+ /** The agent-loop card's staged form over the `agent-loop` settings namespace. */
905
+ /**
906
+ * Namespace of the agent loop's user-owned settings. Spelled here rather than
907
+ * imported: a client package must not depend on a Host package.
908
+ */
909
+ const AGENT_LOOP_NS = "agent-loop";
910
+ /** Bridges the `agent-loop` scope onto the card's staged form. */
911
+ var AgentLoopCardController = class {
912
+ form;
913
+ store;
914
+ /** @param scope - the bound settings scope for the `agent-loop` namespace. */
915
+ constructor(scope) {
916
+ this.form = new _qilin_agent_client_ui_primitives.SettingsFormModel(scope, [(0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxParallelToolCalls")]);
917
+ this.store = this.form.bind(() => this.projection());
918
+ }
919
+ projection() {
920
+ return {
921
+ ...this.form.shell(),
922
+ maxParallelToolCalls: this.form.field("maxParallelToolCalls")
923
+ };
924
+ }
925
+ /**
926
+ * Build the face the card's slot registration injects.
927
+ * @returns the card's snapshot and its form actions.
928
+ */
929
+ inject() {
930
+ return {
931
+ hooks: { agentLoopCard: this.store },
932
+ ...this.form.actions()
933
+ };
934
+ }
935
+ };
936
+ //#endregion
937
+ //#region lib/types/client/bash-card-controller.js
938
+ /** The shell card's staged form over the `bash` settings namespace. */
939
+ /**
940
+ * Namespace of the shell capability. Spelled here rather than imported: a
941
+ * client package must not depend on a Host package, and the executor families
942
+ * that own it spell the same value.
943
+ */
944
+ const SHELL_NS = "shell";
945
+ /** Bridges the `bash` scope onto the shell card's staged form. */
946
+ var BashCardController = class {
947
+ form;
948
+ store;
949
+ /** @param scope - the bound settings scope for the `bash` namespace. */
950
+ constructor(scope) {
951
+ this.form = new _qilin_agent_client_ui_primitives.SettingsFormModel(scope, [(0, _qilin_agent_client_ui_primitives.settingsNumberField)("timeoutMs"), (0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxOutputBytes")]);
952
+ this.store = this.form.bind(() => this.projection());
953
+ }
954
+ projection() {
955
+ return {
956
+ ...this.form.shell(),
957
+ timeoutMs: this.form.field("timeoutMs"),
958
+ maxOutputBytes: this.form.field("maxOutputBytes")
959
+ };
960
+ }
961
+ /**
962
+ * Build the face the card's slot registration injects.
963
+ * @returns the card's snapshot and its form actions.
964
+ */
965
+ inject() {
966
+ return {
967
+ hooks: { bashCard: this.store },
968
+ ...this.form.actions()
969
+ };
970
+ }
971
+ };
972
+ //#endregion
973
+ //#region lib/types/client/git-card-controller.js
974
+ /** The Git card's staged form over the `workspace-git` settings namespace. */
975
+ /**
976
+ * Namespace of the workspace Git service. Spelled here rather than imported:
977
+ * a client package must not depend on a Host package, and the service plugin
978
+ * that owns it spells the same value.
979
+ */
980
+ const GIT_NS = "workspace-git";
981
+ /** Bridges the `workspace-git` scope onto the Git card's staged form. */
982
+ var GitCardController = class {
983
+ form;
984
+ store;
985
+ /** @param scope - the bound settings scope for the `workspace-git` namespace. */
986
+ constructor(scope) {
987
+ this.form = new _qilin_agent_client_ui_primitives.SettingsFormModel(scope, [
988
+ (0, _qilin_agent_client_ui_primitives.settingsTextField)("gitBin"),
989
+ (0, _qilin_agent_client_ui_primitives.settingsTextField)("ghBin"),
990
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("timeoutMs"),
991
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("discoveryTimeoutMs"),
992
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("ghTimeoutMs"),
993
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxDiffBytes"),
994
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxStderrChars"),
995
+ (0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxListEntries")
996
+ ]);
997
+ this.store = this.form.bind(() => this.projection());
998
+ }
999
+ projection() {
1000
+ return {
1001
+ ...this.form.shell(),
1002
+ gitBin: this.form.field("gitBin"),
1003
+ ghBin: this.form.field("ghBin"),
1004
+ timeoutMs: this.form.field("timeoutMs"),
1005
+ discoveryTimeoutMs: this.form.field("discoveryTimeoutMs"),
1006
+ ghTimeoutMs: this.form.field("ghTimeoutMs"),
1007
+ maxDiffBytes: this.form.field("maxDiffBytes"),
1008
+ maxStderrChars: this.form.field("maxStderrChars"),
1009
+ maxListEntries: this.form.field("maxListEntries")
1010
+ };
1011
+ }
1012
+ /**
1013
+ * Build the face the card's slot registration injects.
1014
+ * @returns the card's snapshot and its form actions.
1015
+ */
1016
+ inject() {
1017
+ return {
1018
+ hooks: { gitCard: this.store },
1019
+ ...this.form.actions()
1020
+ };
1021
+ }
1022
+ };
1023
+ //#endregion
1024
+ //#region lib/types/client/subagent-model-selection-card-controller.js
1025
+ /** Staged editor for the Host-owned subagent model allowlist. */
1026
+ /** Namespace of the Host-owned subagent model-selection preference. */
1027
+ const SUBAGENT_MODEL_SELECTION_NS = "subagent-model-selection";
1028
+ /**
1029
+ * Stable identity for one exact route; callers resolve it by lookup and never parse it.
1030
+ * @param route - Provider/model route to identify.
1031
+ * @returns Opaque key for lookup within the card.
1032
+ */
1033
+ function subagentModelKey(route) {
1034
+ return `${route.provider}\0${route.model}`;
1035
+ }
1036
+ /**
1037
+ * Join live adapter metadata with stored routes that remain removable after disappearance.
1038
+ * @param groups - Current model directory grouped by provider.
1039
+ * @param stored - Routes in the effective settings value.
1040
+ * @param selected - Opaque route keys selected in the current draft.
1041
+ * @returns Candidate rows for the card.
1042
+ */
1043
+ function subagentModelCandidates(groups, stored, selected) {
1044
+ const storedByKey = new Map(stored.map((route) => [subagentModelKey(route), route]));
1045
+ const candidates = groups.flatMap((group) => group.models.map((model) => {
1046
+ const route = {
1047
+ provider: group.id,
1048
+ model: model.id
1049
+ };
1050
+ const key = subagentModelKey(route);
1051
+ storedByKey.delete(key);
1052
+ return {
1053
+ ...route,
1054
+ key,
1055
+ providerName: group.name,
1056
+ modelName: model.name,
1057
+ available: true,
1058
+ selected: selected.has(key)
1059
+ };
1060
+ }));
1061
+ for (const route of storedByKey.values()) {
1062
+ const key = subagentModelKey(route);
1063
+ candidates.push({
1064
+ ...route,
1065
+ key,
1066
+ providerName: route.provider,
1067
+ modelName: route.model,
1068
+ available: false,
1069
+ selected: selected.has(key)
1070
+ });
1071
+ }
1072
+ return candidates;
1073
+ }
1074
+ function sameRoutes(left, right) {
1075
+ if (left.length !== right.length) return false;
1076
+ const rightKeys = new Set(right.map(subagentModelKey));
1077
+ return left.every((route) => rightKeys.has(subagentModelKey(route)));
1078
+ }
1079
+ /** Bridges one settings scope and the live adapter directory onto a staged card. */
1080
+ var SubagentModelSelectionCardController = class {
1081
+ scope;
1082
+ ctx;
1083
+ catalogGroups = [];
1084
+ catalogPartial = false;
1085
+ catalogStatus = "idle";
1086
+ draftEnabled;
1087
+ draftRoutes;
1088
+ draftRevision;
1089
+ saving = false;
1090
+ failed = false;
1091
+ conflicted = false;
1092
+ disposed = false;
1093
+ saveGeneration = 0;
1094
+ catalogGeneration = 0;
1095
+ store;
1096
+ unsubscribe;
1097
+ /**
1098
+ * @param scope - bound `subagent-model-selection` settings scope.
1099
+ * @param ctx - the card plugin's context, whose `remote.session` namespace
1100
+ * answers the Host model catalog.
1101
+ */
1102
+ constructor(scope, ctx) {
1103
+ this.scope = scope;
1104
+ this.ctx = ctx;
1105
+ this.store = (0, _qilin_agent_client_store.createSnapshotStore)(this.projection());
1106
+ this.unsubscribe = scope.subscribe(() => {
1107
+ 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();
1108
+ else this.conflicted = true;
1109
+ if (this.enabled() && this.catalogStatus === "idle") this.loadCatalog();
1110
+ this.publish();
1111
+ });
1112
+ if (this.enabled() && this.catalogStatus === "idle") this.loadCatalog();
1113
+ }
1114
+ /** Stop observing settings and suppress late directory/write settlements. */
1115
+ dispose() {
1116
+ this.disposed = true;
1117
+ this.saveGeneration += 1;
1118
+ this.catalogGeneration += 1;
1119
+ this.unsubscribe();
1120
+ }
1121
+ /**
1122
+ * Build the renderer face for this card.
1123
+ * @returns The snapshot and staged card actions injected into the renderer.
1124
+ */
1125
+ inject() {
1126
+ return {
1127
+ hooks: { subagentModelSelectionCard: this.store },
1128
+ toggleEnabled: () => {
1129
+ this.toggleEnabled();
1130
+ },
1131
+ toggleModel: (key) => {
1132
+ this.toggleModel(key);
1133
+ },
1134
+ retryCatalog: () => {
1135
+ this.loadCatalog();
1136
+ },
1137
+ save: () => {
1138
+ this.save();
1139
+ },
1140
+ discard: () => {
1141
+ this.discard();
1142
+ }
1143
+ };
1144
+ }
1145
+ currentRoutes() {
1146
+ return this.scope.getSnapshot().value?.allowedModels.map((route) => ({ ...route })) ?? [];
1147
+ }
1148
+ currentEnabled() {
1149
+ return this.scope.getSnapshot().value?.enabled ?? false;
1150
+ }
1151
+ selected() {
1152
+ return new Set(this.draftRoutes?.keys() ?? this.currentRoutes().map(subagentModelKey));
1153
+ }
1154
+ enabled() {
1155
+ return this.draftEnabled ?? this.currentEnabled();
1156
+ }
1157
+ beginDraft() {
1158
+ if (this.draftRoutes === void 0) {
1159
+ const snapshot = this.scope.getSnapshot();
1160
+ this.draftEnabled = snapshot.value?.enabled ?? false;
1161
+ this.draftRoutes = new Map(snapshot.value?.allowedModels.map((route) => [subagentModelKey(route), { ...route }]) ?? []);
1162
+ this.draftRevision = snapshot.revision;
1163
+ }
1164
+ return this.draftRoutes;
1165
+ }
1166
+ toggleEnabled() {
1167
+ const snapshot = this.scope.getSnapshot();
1168
+ if (this.disposed || snapshot.status !== "ready" || !snapshot.writable || this.saving) return;
1169
+ this.beginDraft();
1170
+ this.draftEnabled = !this.draftEnabled;
1171
+ this.failed = false;
1172
+ if (this.draftEnabled && this.catalogStatus === "idle") this.loadCatalog();
1173
+ this.publish();
1174
+ }
1175
+ toggleModel(key) {
1176
+ if (!this.enabled() || this.saving || !this.scope.getSnapshot().writable) return;
1177
+ const candidate = this.candidates().find((candidate) => candidate.key === key);
1178
+ if (candidate === void 0) return;
1179
+ const routes = this.beginDraft();
1180
+ if (routes.has(key)) routes.delete(key);
1181
+ else routes.set(key, {
1182
+ provider: candidate.provider,
1183
+ model: candidate.model
1184
+ });
1185
+ this.failed = false;
1186
+ this.publish();
1187
+ }
1188
+ clearDraft() {
1189
+ this.draftEnabled = void 0;
1190
+ this.draftRoutes = void 0;
1191
+ this.draftRevision = void 0;
1192
+ this.failed = false;
1193
+ this.conflicted = false;
1194
+ }
1195
+ discard() {
1196
+ if (this.saving) return;
1197
+ this.clearDraft();
1198
+ this.publish();
1199
+ }
1200
+ candidates() {
1201
+ const retained = new Map(this.currentRoutes().map((route) => [subagentModelKey(route), route]));
1202
+ for (const [key, route] of this.draftRoutes ?? []) retained.set(key, route);
1203
+ return subagentModelCandidates(this.catalogGroups, [...retained.values()], this.selected());
1204
+ }
1205
+ desiredRoutes() {
1206
+ return [...this.draftRoutes?.values() ?? this.currentRoutes()].map((route) => ({ ...route }));
1207
+ }
1208
+ async save() {
1209
+ const snapshot = this.scope.getSnapshot();
1210
+ const desiredEnabled = this.enabled();
1211
+ const desired = this.desiredRoutes();
1212
+ if (this.disposed || snapshot.status !== "ready" || !snapshot.writable || this.saving || this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired) || desiredEnabled && desired.length === 0) return;
1213
+ if (this.draftRoutes !== void 0 && snapshot.revision !== this.draftRevision) {
1214
+ this.conflicted = true;
1215
+ this.publish();
1216
+ return;
1217
+ }
1218
+ const generation = this.saveGeneration;
1219
+ this.saving = true;
1220
+ this.failed = false;
1221
+ this.conflicted = false;
1222
+ this.publish();
1223
+ await this.scope.mutate([{
1224
+ op: "set",
1225
+ path: ["enabled"],
1226
+ value: desiredEnabled
1227
+ }, {
1228
+ op: "set",
1229
+ path: ["allowedModels"],
1230
+ value: desired.map((route) => ({
1231
+ provider: route.provider,
1232
+ model: route.model
1233
+ }))
1234
+ }], this.draftRevision);
1235
+ if (generation !== this.saveGeneration) return;
1236
+ const landed = this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired);
1237
+ this.saving = false;
1238
+ this.failed = !landed;
1239
+ if (landed) this.clearDraft();
1240
+ this.publish();
1241
+ }
1242
+ /** Invalidate and reload model candidates after a Host model input changes. */
1243
+ refreshCatalog() {
1244
+ if (this.disposed) return;
1245
+ this.catalogGeneration += 1;
1246
+ this.catalogStatus = "idle";
1247
+ this.catalogPartial = false;
1248
+ if (this.enabled()) this.loadCatalog();
1249
+ else this.publish();
1250
+ }
1251
+ /** Drop Host-specific candidates and drafts, then reload after reconnecting. */
1252
+ resetConnection() {
1253
+ if (this.disposed) return;
1254
+ this.saveGeneration += 1;
1255
+ this.saving = false;
1256
+ this.clearDraft();
1257
+ this.catalogGroups = [];
1258
+ this.refreshCatalog();
1259
+ }
1260
+ async loadCatalog() {
1261
+ if (this.disposed || this.catalogStatus === "loading") return;
1262
+ const generation = this.catalogGeneration;
1263
+ this.catalogStatus = "loading";
1264
+ this.catalogPartial = false;
1265
+ this.publish();
1266
+ const response = await this.ctx.remote.session.modelCatalog();
1267
+ if (generation !== this.catalogGeneration) return;
1268
+ if (response.ok) {
1269
+ this.catalogGroups = response.value.groups;
1270
+ this.catalogPartial = response.value.failures.length > 0;
1271
+ this.catalogStatus = "ready";
1272
+ } else this.catalogStatus = "error";
1273
+ this.publish();
1274
+ }
1275
+ projection() {
1276
+ const snapshot = this.scope.getSnapshot();
1277
+ const current = this.currentRoutes();
1278
+ const desired = this.desiredRoutes();
1279
+ const enabled = this.enabled();
1280
+ return {
1281
+ available: snapshot.status === "ready",
1282
+ writable: snapshot.writable,
1283
+ dirty: this.currentEnabled() !== enabled || !sameRoutes(current, desired),
1284
+ invalid: enabled && desired.length === 0,
1285
+ saving: this.saving,
1286
+ failed: this.failed,
1287
+ enabled,
1288
+ candidates: this.candidates(),
1289
+ catalogStatus: this.catalogStatus,
1290
+ catalogPartial: this.catalogPartial,
1291
+ conflicted: this.conflicted
1292
+ };
1293
+ }
1294
+ publish() {
1295
+ this.store.set(this.projection());
1296
+ }
1297
+ };
1298
+ //#endregion
1299
+ //#region lib/types/client/web-search-card-controller.js
1300
+ /**
1301
+ * The web-search card's staged form over the `web-search-deepseek` settings
1302
+ * namespace.
1303
+ *
1304
+ * The key is the one control that does not live in the section: its literal
1305
+ * never rides a response, so the card learns only whether one is configured
1306
+ * and writes it through the credentials domain, addressed by the reference the
1307
+ * section names. It is still staged with the rest of the form, so one save
1308
+ * covers everything the card shows.
1309
+ */
1310
+ /**
1311
+ * Namespace of the DeepSeek search provider. Spelled here rather than
1312
+ * imported: a client package must not depend on a Host package.
1313
+ */
1314
+ const WEB_SEARCH_NS = "web-search-deepseek";
1315
+ /** Credential reference the provider resolves when the section names none. */
1316
+ const DEFAULT_API_KEY_REF = "DEEPSEEK_API_KEY";
1317
+ /** Form field the credential control stages under. */
1318
+ const API_KEY_FIELD = "apiKey";
1319
+ /** Bridges the `web-search-deepseek` scope and the credentials domain onto the card. */
1320
+ var WebSearchCardController = class {
1321
+ scope;
1322
+ ctx;
1323
+ form;
1324
+ store;
1325
+ credential = {
1326
+ ref: "",
1327
+ configured: false,
1328
+ writable: true
1329
+ };
1330
+ /**
1331
+ * @param scope - the bound settings scope for the `web-search-deepseek` namespace.
1332
+ * @param ctx - the card plugin's context, whose `remote.credentials` namespace
1333
+ * answers for the credential the section references.
1334
+ */
1335
+ constructor(scope, ctx) {
1336
+ this.scope = scope;
1337
+ this.ctx = ctx;
1338
+ this.form = new _qilin_agent_client_ui_primitives.SettingsFormModel(scope, [(0, _qilin_agent_client_ui_primitives.settingsTextField)("baseURL"), (0, _qilin_agent_client_ui_primitives.settingsNumberField)("maxUses")], [{
1339
+ field: API_KEY_FIELD,
1340
+ write: (text) => this.writeKey(text)
1341
+ }]);
1342
+ this.store = this.form.bind(() => this.projection());
1343
+ scope.subscribe(() => {
1344
+ this.readCredential();
1345
+ });
1346
+ this.readCredential();
1347
+ }
1348
+ projection() {
1349
+ return {
1350
+ ...this.form.shell(),
1351
+ baseURL: this.form.field("baseURL"),
1352
+ maxUses: this.form.field("maxUses"),
1353
+ apiKey: this.form.field(API_KEY_FIELD),
1354
+ apiKeyConfigured: this.credential.configured,
1355
+ apiKeyWritable: this.credential.writable
1356
+ };
1357
+ }
1358
+ /**
1359
+ * Ask the credentials domain about the reference the section currently names.
1360
+ *
1361
+ * The answer is stored with the reference it describes: `apiKeyEnv` can
1362
+ * change between the request and its response, and two reads can settle out
1363
+ * of order, so a response is published only while it still answers for the
1364
+ * reference in force.
1365
+ */
1366
+ async readCredential() {
1367
+ const ref = refOf(this.scope.getSnapshot());
1368
+ if (ref !== this.credential.ref) {
1369
+ this.credential = {
1370
+ ref,
1371
+ configured: false,
1372
+ writable: true
1373
+ };
1374
+ this.store.set(this.projection());
1375
+ }
1376
+ const response = await this.ctx.remote.credentials.describe([ref]);
1377
+ if (!response.ok || ref !== refOf(this.scope.getSnapshot())) return;
1378
+ const view = response.value[ref];
1379
+ const next = {
1380
+ ref,
1381
+ configured: view?.configured ?? false,
1382
+ writable: view?.writable ?? true
1383
+ };
1384
+ if (next.configured === this.credential.configured && next.writable === this.credential.writable) return;
1385
+ this.credential = next;
1386
+ this.store.set(this.projection());
1387
+ }
1388
+ /**
1389
+ * Re-read after the Host reports a change to the reference this card watches.
1390
+ *
1391
+ * A key can be written from somewhere else — the Models page addresses the
1392
+ * same reference — and the settings section does not change when it is, so
1393
+ * without this the badge keeps reporting a state the Host already replaced.
1394
+ * @param ref - the reference the Host reports as changed.
1395
+ */
1396
+ refreshCredential(ref) {
1397
+ if (ref !== this.credential.ref) return;
1398
+ this.readCredential();
1399
+ }
1400
+ /**
1401
+ * Build the face the card's slot registration injects.
1402
+ * @returns the card's snapshot and its form actions.
1403
+ */
1404
+ inject() {
1405
+ return {
1406
+ hooks: { webSearchCard: this.store },
1407
+ ...this.form.actions()
1408
+ };
1409
+ }
1410
+ /**
1411
+ * Write the staged key, then re-read whether the Host now holds one.
1412
+ * @param value - the staged credential literal.
1413
+ * @returns whether the Host reports a configured credential afterwards.
1414
+ */
1415
+ async writeKey(value) {
1416
+ await this.ctx.remote.credentials.set(refOf(this.scope.getSnapshot()), value);
1417
+ await this.readCredential();
1418
+ return this.credential.configured;
1419
+ }
1420
+ };
1421
+ /**
1422
+ * The credential reference the section names, or the provider's default.
1423
+ * @param snapshot - the current scope snapshot.
1424
+ * @returns the reference to address.
1425
+ */
1426
+ function refOf(snapshot) {
1427
+ const declared = snapshot.value?.apiKeyEnv;
1428
+ return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_API_KEY_REF;
1429
+ }
1430
+ //#endregion
1431
+ //#region lib/types/client/locales.js
1432
+ /** Locale bundles for the built-in plugins settings section and the plugin configuration pages. */
1433
+ /** English copy. */
1434
+ const en = {
1435
+ nav: "Built-in plugins",
1436
+ title: "Built-in plugins",
1437
+ intro: "Inspect the plugins this deployment ships.",
1438
+ tabs: "Plugin views",
1439
+ empty: "This deployment exposes no plugin views.",
1440
+ overridden: "Overridden",
1441
+ reset: "Reset to default",
1442
+ readOnly: "This deployment stores settings read-only.",
1443
+ unavailable: "This plugin is not loaded, so it cannot be configured right now.",
1444
+ save: "Save",
1445
+ saving: "Saving…",
1446
+ saveFailed: "The deployment did not accept these values; they were left for you to correct.",
1447
+ invalidNumber: "Enter a number, or leave blank to use the default.",
1448
+ bashTitle: "Shell",
1449
+ bashDescription: "Limits every command the agent runs.",
1450
+ bashTimeoutMs: "Command timeout (ms)",
1451
+ bashTimeoutMsHint: "How long one command may run before it is terminated.",
1452
+ bashMaxOutputBytes: "Output cap per stream (bytes)",
1453
+ bashMaxOutputBytesHint: "Output beyond this spills to a temporary file rather than being lost.",
1454
+ agentLoopTitle: "Agent loop",
1455
+ agentLoopDescription: "How the agent dispatches tool calls.",
1456
+ agentLoopMaxParallel: "Parallel tool calls",
1457
+ agentLoopMaxParallelHint: "Upper bound on parallel-safe calls running at once within one step.",
1458
+ gitTitle: "Git repositories",
1459
+ gitDescription: "Binaries and limits behind repository status, commits, and pull requests.",
1460
+ gitBin: "Git executable",
1461
+ gitBinHint: "Path of the git binary every repository call spawns.",
1462
+ ghBin: "gh executable",
1463
+ ghBinHint: "Path of the gh binary every pull-request call spawns.",
1464
+ gitTimeoutMs: "Command timeout (ms)",
1465
+ gitTimeoutMsHint: "How long one diff or mutation command may run before it is killed.",
1466
+ gitDiscoveryTimeoutMs: "Discovery timeout (ms)",
1467
+ gitDiscoveryTimeoutMsHint: "How long repository discovery may run; failing workspaces read as not a repository.",
1468
+ ghTimeoutMs: "gh timeout (ms)",
1469
+ ghTimeoutMsHint: "How long one GitHub API call may run; gh is slower than local git.",
1470
+ gitMaxDiffBytes: "Diff cap (bytes)",
1471
+ gitMaxDiffBytesHint: "A larger diff fails with too-large instead of being shortened.",
1472
+ gitMaxStderrChars: "Error detail cap (chars)",
1473
+ gitMaxStderrCharsHint: "How many stderr characters one failure answer carries.",
1474
+ gitMaxListEntries: "List cap (entries)",
1475
+ gitMaxListEntriesHint: "Upper bound on branches or pull requests one list answer returns.",
1476
+ webSearchTitle: "Web search",
1477
+ webSearchDescription: "The DeepSeek search provider.",
1478
+ webSearchApiKey: "API key",
1479
+ webSearchApiKeyHint: "Stored outside the settings file. Leave blank to keep the current key.",
1480
+ webSearchApiKeySet: "A key is configured.",
1481
+ webSearchApiKeyUnset: "No key is configured; search is unavailable until one is.",
1482
+ webSearchBaseUrl: "Endpoint",
1483
+ webSearchBaseUrlHint: "Leave blank to use the provider default.",
1484
+ webSearchMaxUses: "Max searches per request",
1485
+ webSearchMaxUsesHint: "How many times one request may search before it must answer.",
1486
+ subagentTitle: "Subagent",
1487
+ subagentDescription: "Set Subagent recursion depth, count, and models.",
1488
+ subagentLimitsTitle: "Limits",
1489
+ subagentMaxDepth: "Maximum recursion depth",
1490
+ subagentDepthHelpLabel: "About maximum recursion depth",
1491
+ subagentDepthHelp: "Limits how many levels of Subagents an Agent can create.",
1492
+ subagentDepthZero: "Disable Subagents",
1493
+ subagentDepthOne: "Only the main Agent can create Subagents",
1494
+ subagentDepthOverride: "If a tool defines its own maximum recursion depth, that setting takes precedence.",
1495
+ subagentMaxActive: "Subagent parallelism limit",
1496
+ subagentCapacityHelpLabel: "About the Subagent parallelism limit",
1497
+ 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.",
1498
+ subagentDepthInvalid: "Enter a whole number of 0 or more.",
1499
+ subagentCapacityInvalid: "Enter a whole number of 1 or more.",
1500
+ subagentModelSelectionTitle: "Model selection",
1501
+ subagentModelSelectionToggle: "Allow agents to choose models for Subagents",
1502
+ 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.",
1503
+ subagentModelSelectionAllowed: "Models agents may choose",
1504
+ subagentModelSelectionLoading: "Loading models…",
1505
+ subagentModelSelectionLoadFailed: "Models could not be loaded.",
1506
+ subagentModelSelectionRetry: "Retry",
1507
+ subagentModelSelectionPartial: "Some model providers could not be loaded; saved choices remain removable.",
1508
+ subagentModelSelectionUnavailable: "Currently unavailable",
1509
+ subagentModelSelectionUnavailableGroup: "Saved but currently unavailable",
1510
+ subagentModelSelectionEmpty: "No model provider currently advertises a model.",
1511
+ subagentModelSelectionRequired: "Select at least one model before saving.",
1512
+ subagentModelSelectionConflict: "Settings changed elsewhere. Discard your draft and try again.",
1513
+ subagentModelSelectionOff: "Subagents use configured defaults or inherit the parent agent's model. Saved model choices are retained."
1514
+ };
1515
+ /** Simplified Chinese copy. */
1516
+ const zh = {
1517
+ nav: "内置插件",
1518
+ title: "内置插件",
1519
+ intro: "查看内置部署的插件列表",
1520
+ tabs: "插件视图",
1521
+ empty: "本部署没有开放任何插件视图。",
1522
+ overridden: "已覆盖",
1523
+ reset: "恢复默认",
1524
+ readOnly: "本部署的设置为只读。",
1525
+ unavailable: "该插件当前未加载,暂时无法配置。",
1526
+ save: "保存",
1527
+ saving: "保存中…",
1528
+ saveFailed: "本部署没有接受这些值,已保留供你修改。",
1529
+ invalidNumber: "请填数字;留空表示使用默认值。",
1530
+ bashTitle: "终端",
1531
+ bashDescription: "限制 agent 运行的每一条命令。",
1532
+ bashTimeoutMs: "命令超时(毫秒)",
1533
+ bashTimeoutMsHint: "单条命令允许运行多久,超时即终止。",
1534
+ bashMaxOutputBytes: "单流输出上限(字节)",
1535
+ bashMaxOutputBytesHint: "超出部分会转存到临时文件,而不是被丢弃。",
1536
+ agentLoopTitle: "Agent 循环",
1537
+ agentLoopDescription: "Agent 如何派发工具调用。",
1538
+ agentLoopMaxParallel: "并行工具调用数",
1539
+ agentLoopMaxParallelHint: "同一步内最多同时运行多少个可并行的调用。",
1540
+ gitTitle: "Git 仓库",
1541
+ gitDescription: "仓库状态、提交与拉取请求背后的二进制与限额。",
1542
+ gitBin: "Git 可执行文件",
1543
+ gitBinHint: "每次仓库调用启动的 git 二进制路径。",
1544
+ ghBin: "gh 可执行文件",
1545
+ ghBinHint: "每次拉取请求调用启动的 gh 二进制路径。",
1546
+ gitTimeoutMs: "命令超时(毫秒)",
1547
+ gitTimeoutMsHint: "单条差异或变更命令允许运行多久,超时即被终止。",
1548
+ gitDiscoveryTimeoutMs: "发现超时(毫秒)",
1549
+ gitDiscoveryTimeoutMsHint: "仓库发现允许运行多久;失败的工作区按「不是仓库」应答。",
1550
+ ghTimeoutMs: "gh 超时(毫秒)",
1551
+ ghTimeoutMsHint: "单次 GitHub API 调用允许运行多久;gh 比本地 git 慢。",
1552
+ gitMaxDiffBytes: "差异上限(字节)",
1553
+ gitMaxDiffBytesHint: "超过上限的差异以 too-large 失败,而不是被截短。",
1554
+ gitMaxStderrChars: "错误详情上限(字符)",
1555
+ gitMaxStderrCharsHint: "一次失败应答携带多少 stderr 字符。",
1556
+ gitMaxListEntries: "列表上限(条)",
1557
+ gitMaxListEntriesHint: "一次列表应答最多返回多少分支或拉取请求。",
1558
+ webSearchTitle: "网页搜索",
1559
+ webSearchDescription: "DeepSeek 搜索提供方。",
1560
+ webSearchApiKey: "API Key",
1561
+ webSearchApiKeyHint: "不写入设置文件。留空表示保持当前密钥。",
1562
+ webSearchApiKeySet: "已配置密钥。",
1563
+ webSearchApiKeyUnset: "未配置密钥;配置之前搜索不可用。",
1564
+ webSearchBaseUrl: "接口地址",
1565
+ webSearchBaseUrlHint: "留空则使用提供方默认地址。",
1566
+ webSearchMaxUses: "单次请求最多搜索次数",
1567
+ webSearchMaxUsesHint: "一次请求在必须作答前最多可以搜索多少次。",
1568
+ subagentTitle: "Subagent",
1569
+ subagentDescription: "设置 Subagent 的递归层级、数量和模型。",
1570
+ subagentLimitsTitle: "运行限制",
1571
+ subagentMaxDepth: "最大递归深度",
1572
+ subagentDepthHelpLabel: "最大递归深度说明",
1573
+ subagentDepthHelp: "限制 Agent 创建 Subagent 的递归层级。",
1574
+ subagentDepthZero: "禁用 Subagent",
1575
+ subagentDepthOne: "仅允许主 Agent 创建 Subagent",
1576
+ subagentDepthOverride: "如果某个工具单独设置了最大递归深度,以该工具的设置为准。",
1577
+ subagentMaxActive: "Subagent 并行数量上限",
1578
+ subagentCapacityHelpLabel: "Subagent 并行数量上限说明",
1579
+ subagentCapacityHelp: "同一主 Agent 下,所有递归层级同时存活的 Subagent 总数,主 Agent 不计入。达到上限时,新的启动请求会被拒绝。",
1580
+ subagentDepthInvalid: "请输入不小于 0 的整数。",
1581
+ subagentCapacityInvalid: "请输入不小于 1 的整数。",
1582
+ subagentModelSelectionTitle: "模型选择",
1583
+ subagentModelSelectionToggle: "允许 Agent 为 Subagent 选择模型",
1584
+ subagentModelSelectionChoose: "开启后,Agent 可以从下方授权模型中,为每个 Subagent 选择提供方、模型和推理强度。仅影响新会话。",
1585
+ subagentModelSelectionAllowed: "Agent 可选择的模型",
1586
+ subagentModelSelectionLoading: "正在加载模型…",
1587
+ subagentModelSelectionLoadFailed: "无法加载模型。",
1588
+ subagentModelSelectionRetry: "重试",
1589
+ subagentModelSelectionPartial: "部分模型提供方暂时无法加载;已保存的选择仍可移除。",
1590
+ subagentModelSelectionUnavailable: "当前不可用",
1591
+ subagentModelSelectionUnavailableGroup: "已保存但当前不可用",
1592
+ subagentModelSelectionEmpty: "当前没有模型提供方公布模型。",
1593
+ subagentModelSelectionRequired: "保存前请至少选择一个模型。",
1594
+ subagentModelSelectionConflict: "设置已在其他位置更新。请放弃修改后重试。",
1595
+ subagentModelSelectionOff: "关闭后,Subagent 使用配置的默认模型或继承父 Agent 的模型;已选模型会保留。"
1596
+ };
1597
+ //#endregion
1598
+ //#region lib/types/client/index.js
1599
+ /**
1600
+ * Built-in plugins settings surface and the official plugin configuration
1601
+ * pages, browser half. The Settings section is the shell around the
1602
+ * feature-owned tabs registered into `settings.plugins.tab` (the read-only
1603
+ * inventory ships one); the configuration pages this package ships register
1604
+ * into the Plugins page's `plugins.item` slot, for the host-plane namespaces
1605
+ * the deployment exposes, and appear in the page's Official group. Each form
1606
+ * binds its namespace through the client settings scope, which keeps the
1607
+ * pages unaware of one another and of the section.
1608
+ */
1609
+ /** Dictionary namespace owned by this plugin. */
1610
+ const NS = "settings.plugins";
1611
+ /** Required services (cordis fiber inject). */
1612
+ const inject = [
1613
+ "slots",
1614
+ "locale",
1615
+ "remote",
1616
+ "remote.credentials",
1617
+ "remote.session",
1618
+ "configForms"
1619
+ ];
1620
+ /**
1621
+ * Mount the built-in plugins section and the configuration pages this package ships.
1622
+ * @param ctx - the browser plugin context.
1623
+ */
1624
+ function apply(ctx) {
1625
+ const t = ctx.locale.bind(NS);
1626
+ ctx.effect(() => ctx.locale.register(NS, {
1627
+ zh,
1628
+ en
1629
+ }), "ui-settings-plugins: section dictionaries");
1630
+ const bash = new BashCardController(ctx.configForms.get(SHELL_NS));
1631
+ const git = new GitCardController(ctx.configForms.get(GIT_NS));
1632
+ const agentLoop = new AgentLoopCardController(ctx.configForms.get(AGENT_LOOP_NS));
1633
+ const webSearch = new WebSearchCardController(ctx.configForms.get(WEB_SEARCH_NS), ctx);
1634
+ const subagentLimits = new SubagentLimitsCardController(ctx.configForms.get("subagent"));
1635
+ const subagentModelSelection = new SubagentModelSelectionCardController(ctx.configForms.get(SUBAGENT_MODEL_SELECTION_NS), ctx);
1636
+ const subagentLimitsFace = subagentLimits.inject();
1637
+ const subagentModelsFace = subagentModelSelection.inject();
1638
+ ctx.effect(() => ctx.remote.$on("credentials/reference-updated", (ref) => {
1639
+ webSearch.refreshCredential(ref);
1640
+ }), "ui-settings-plugins: credential invalidations");
1641
+ ctx.effect(() => ctx.remote.$on("llm/adapters-updated", () => {
1642
+ subagentModelSelection.refreshCatalog();
1643
+ }), "ui-settings-plugins: subagent adapter invalidations");
1644
+ ctx.effect(() => ctx.remote.$on("settings/document-updated", () => {
1645
+ subagentModelSelection.refreshCatalog();
1646
+ }), "ui-settings-plugins: subagent settings invalidations");
1647
+ ctx.effect(() => ctx.on("connection/reset", () => {
1648
+ subagentModelSelection.resetConnection();
1649
+ }), "ui-settings-plugins: subagent connection generation");
1650
+ ctx.effect(() => () => {
1651
+ subagentModelSelection.dispose();
1652
+ }, "ui-settings-plugins: subagent preference");
1653
+ const pages = [
1654
+ [[SHELL_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
1655
+ name: "plugins.item",
1656
+ id: "bash",
1657
+ order: 10,
1658
+ label: () => t("bashTitle"),
1659
+ locale: NS,
1660
+ inject: () => bash.inject()
1661
+ }, BashCard))],
1662
+ [[GIT_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
1663
+ name: "plugins.item",
1664
+ id: "git",
1665
+ order: 15,
1666
+ label: () => t("gitTitle"),
1667
+ locale: NS,
1668
+ inject: () => git.inject()
1669
+ }, GitCard))],
1670
+ [[AGENT_LOOP_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
1671
+ name: "plugins.item",
1672
+ id: "agent-loop",
1673
+ order: 20,
1674
+ label: () => t("agentLoopTitle"),
1675
+ locale: NS,
1676
+ inject: () => agentLoop.inject()
1677
+ }, AgentLoopCard))],
1678
+ [["subagent", SUBAGENT_MODEL_SELECTION_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
1679
+ name: "plugins.item",
1680
+ id: "subagent",
1681
+ order: 30,
1682
+ label: () => t("subagentTitle"),
1683
+ locale: NS,
1684
+ inject: () => subagentCardFace(subagentLimitsFace, subagentModelsFace)
1685
+ }, SubagentCard))],
1686
+ [[WEB_SEARCH_NS], () => ctx.slots.inject("plugins.item", () => ctx.slots.register({
1687
+ name: "plugins.item",
1688
+ id: "web-search",
1689
+ order: 40,
1690
+ label: () => t("webSearchTitle"),
1691
+ locale: NS,
1692
+ inject: () => webSearch.inject()
1693
+ }, WebSearchCard))]
1694
+ ];
1695
+ ctx.effect(() => {
1696
+ const offs = pages.map(([namespaces, register]) => ctx.configForms.whileServed([...namespaces], () => register()));
1697
+ return () => {
1698
+ for (const off of offs) off();
1699
+ };
1700
+ }, "ui-settings-plugins: configuration pages");
1701
+ let tabsVersion = -1;
1702
+ let tabsRevision = -1;
1703
+ let tabs = [];
1704
+ const sectionInjected = () => ({ hooks: { tabs: {
1705
+ getSnapshot: () => {
1706
+ const version = ctx.slots.getVersion("settings.plugins.tab");
1707
+ const revision = ctx.locale.getSnapshot().revision;
1708
+ if (version !== tabsVersion || revision !== tabsRevision) {
1709
+ tabsVersion = version;
1710
+ tabsRevision = revision;
1711
+ tabs = ctx.slots.entries("settings.plugins.tab").map((entry) => ({
1712
+ /* v8 ignore next -- list-slot registration requires id */
1713
+ id: entry.options.id ?? "",
1714
+ order: entry.options.order ?? 0,
1715
+ label: (0, _qilin_agent_client_ui_slots.resolveSlotLabel)(entry.options.label) ?? ""
1716
+ })).sort((a, b) => a.order - b.order);
1717
+ }
1718
+ return tabs;
1719
+ },
1720
+ subscribe: (listener) => {
1721
+ const offLedger = ctx.slots.subscribe("settings.plugins.tab", listener);
1722
+ const offLocale = ctx.locale.subscribe(listener);
1723
+ return () => {
1724
+ offLedger();
1725
+ offLocale();
1726
+ };
1727
+ }
1728
+ } } });
1729
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
1730
+ name: "settings.section",
1731
+ id: "plugins",
1732
+ order: 15,
1733
+ label: () => t("nav"),
1734
+ locale: NS,
1735
+ inject: sectionInjected,
1736
+ children: { "settings.plugins.tab": {
1737
+ kind: "list",
1738
+ scope: "root"
1739
+ } }
1740
+ }, PluginsSettingsSection));
1741
+ }
1742
+ //#endregion
1743
+ exports.apply = apply;
1744
+ exports.inject = inject;
1745
+ return module.exports;
1746
+ }
1747
+ });
1748
+
1749
+ //# sourceMappingURL=client.js.map