dsh-tool-web-enhanced-ui 0.1.0 → 0.1.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.md +10 -4
- package/lib/client.cjs +236 -196
- package/lib/client.cjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,10 +15,16 @@ Provides the shared connection menu, activation prompt and profile overview
|
|
|
15
15
|
without depending on either provider row:
|
|
16
16
|
|
|
17
17
|
- **Composer button and menu**: one tab per running search or fetch plugin,
|
|
18
|
-
to pick a connection or Off for the conversation.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
to pick a connection or Off for the conversation. A panel lists the
|
|
19
|
+
connections that are turned on (plus the conversation's own choice if it
|
|
20
|
+
was turned off since), and, when all of that capability's remote services
|
|
21
|
+
are off, a footer link saying more services can be turned on in settings.
|
|
22
|
+
The button collapses to its globe together with DSH's model selector when
|
|
23
|
+
the composer row is short of room. The Agent's enhanced-tool calls never
|
|
24
|
+
show up here.
|
|
25
|
+
- **Activation prompt**: shown once when the profile is enabled; it also says
|
|
26
|
+
remote services are off by default, unless the upgrade check found a
|
|
27
|
+
problem, in which case it points to the overview instead.
|
|
22
28
|
- **Bundle overview** on the profile's Plugins page: whether the `web` row
|
|
23
29
|
routes each capability to this profile, whether a plugin row is disabled,
|
|
24
30
|
and an upgrade check for 0.1.x leftovers.
|
package/lib/client.cjs
CHANGED
|
@@ -5,9 +5,9 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
-
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
9
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
11
11
|
let react_dom = require("react-dom");
|
|
12
12
|
//#region ../core/src/shared/ids.ts
|
|
13
13
|
/**
|
|
@@ -21,12 +21,20 @@ window.__ModuleLoader__.load({
|
|
|
21
21
|
const SEARCH = {
|
|
22
22
|
packageName: "dsh-web-search-enhanced",
|
|
23
23
|
rowId: "web-search-enhanced",
|
|
24
|
-
providerId: "search-enhanced"
|
|
24
|
+
providerId: "search-enhanced",
|
|
25
|
+
tools: {
|
|
26
|
+
action: "web_search_enhanced",
|
|
27
|
+
list: "list_web_search_providers"
|
|
28
|
+
}
|
|
25
29
|
};
|
|
26
30
|
const FETCH = {
|
|
27
31
|
packageName: "dsh-web-fetch-enhanced",
|
|
28
32
|
rowId: "web-fetch-enhanced",
|
|
29
|
-
providerId: "fetch-enhanced"
|
|
33
|
+
providerId: "fetch-enhanced",
|
|
34
|
+
tools: {
|
|
35
|
+
action: "web_fetch_enhanced",
|
|
36
|
+
list: "list_web_fetch_providers"
|
|
37
|
+
}
|
|
30
38
|
};
|
|
31
39
|
/** The browser-only row holding the shared composer connection menu. */
|
|
32
40
|
const UI = {
|
|
@@ -160,7 +168,7 @@ window.__ModuleLoader__.load({
|
|
|
160
168
|
onClick: onOpenDetails,
|
|
161
169
|
children: t("activation.open")
|
|
162
170
|
})] }),
|
|
163
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t(
|
|
171
|
+
children: hasIssues ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("activation.preflight") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("activation.body") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("activation.remoteOff") })] })
|
|
164
172
|
});
|
|
165
173
|
}
|
|
166
174
|
//#endregion
|
|
@@ -198,8 +206,8 @@ window.__ModuleLoader__.load({
|
|
|
198
206
|
return row !== void 0 && !row.enabled;
|
|
199
207
|
}
|
|
200
208
|
//#endregion
|
|
201
|
-
//#region \0dsh-css-module:/
|
|
202
|
-
const css$1 = ".
|
|
209
|
+
//#region \0dsh-css-module:/home/runner/work/dsh-tool-web-enhanced/dsh-tool-web-enhanced/packages/ui/src/client/ComposerConnectionMenu.module.css.mjs
|
|
210
|
+
const css$1 = "._5i6sLq_root{min-width:0;position:relative}._5i6sLq_trigger{border-radius:var(--dsw-radius-sm);min-width:0;max-width:min(320px,42cqw);height:28px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:none;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:400;line-height:20px;display:flex;position:relative}._5i6sLq_trigger:hover,._5i6sLq_trigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}._5i6sLq_trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}._5i6sLq_icon{flex:none;display:flex;position:relative}._5i6sLq_labels{display:var(--dsh-composer-model-text-display,block);min-width:0}._5i6sLq_iconMarks{display:var(--dsh-composer-model-icon-display,none);pointer-events:none;position:absolute;inset:0}._5i6sLq_iconMark{display:flex;position:absolute;top:-3px;right:-5px}._5i6sLq_iconMark[data-mark=fetch]{top:auto;bottom:-3px}._5i6sLq_sides{align-items:center;gap:6px;min-width:0;display:flex}._5i6sLq_side{align-items:center;gap:4px;min-width:0;display:flex}._5i6sLq_sideLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._5i6sLq_sideSeparator{color:var(--dsw-alias-label-caption);flex:none}._5i6sLq_sideMark{pointer-events:none;flex:none}._5i6sLq_chevron,._5i6sLq_busy{flex:none}._5i6sLq_chevron{color:var(--dsw-alias-label-caption);transition:transform .12s}._5i6sLq_chevronOpen{transform:rotate(180deg)}@media (prefers-reduced-motion:reduce){._5i6sLq_chevron{transition:none}}._5i6sLq_menu{z-index:1100;box-sizing:border-box;flex-direction:column;width:min(320px,100vw - 24px);max-width:calc(100vw - 48px);max-height:min(480px,100vh - 32px);display:flex;position:fixed;overflow:hidden}._5i6sLq_panels{flex:auto;grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr);min-height:0;display:grid}._5i6sLq_panel{flex-direction:column;grid-area:1/1;min-width:0;min-height:0;display:flex}._5i6sLq_panelInactive{visibility:hidden}._5i6sLq_panelHeader{box-sizing:border-box;border-bottom:.5px solid var(--dsw-alias-border-l2);flex:none;align-items:center;gap:8px;min-height:36px;padding:4px 4px 4px 12px;display:flex}._5i6sLq_summary{min-width:0;color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:auto;align-items:center;gap:4px;margin:0;font-size:12px;line-height:20px;display:flex}._5i6sLq_summaryCurrent,._5i6sLq_summarySource{text-overflow:ellipsis;min-width:0;overflow:hidden}._5i6sLq_summaryCurrent{color:var(--dsw-alias-label-primary);flex:0 auto}._5i6sLq_summarySeparator{color:var(--dsw-alias-label-caption);flex:none}._5i6sLq_summarySource{flex:0 2 auto}._5i6sLq_settingsButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;place-items:center;padding:0;display:grid}._5i6sLq_settingsButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._5i6sLq_panelBody{overscroll-behavior:contain;flex:auto;min-height:0;padding:4px 0;overflow-y:auto}._5i6sLq_row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;border-radius:var(--dsw-radius-xs);background:0 0;border:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 12px;font-size:13px;line-height:18px;display:flex}._5i6sLq_row:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._5i6sLq_settingsButton:focus-visible,._5i6sLq_row:focus-visible{box-shadow:inset 0 0 0 1.5px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._5i6sLq_row:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}._5i6sLq_rowContent{flex-direction:column;flex:auto;min-width:0;display:flex}._5i6sLq_rowLabel{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._5i6sLq_rowCaption{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px}._5i6sLq_rowCaptionWarn{color:var(--dsw-alias-label-secondary);align-items:center;gap:4px;display:inline-flex}._5i6sLq_warnDot{background:var(--dsw-alias-state-warn-label);border-radius:50%;flex:none;width:5px;height:5px;display:inline-block}._5i6sLq_check{color:var(--dsw-alias-label-secondary);flex:0 0 16px;justify-content:center;align-items:center;display:flex}._5i6sLq_routeNotice,._5i6sLq_disabledNotice{border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-label-secondary);align-items:flex-start;gap:8px;margin:4px 8px;padding:6px 12px;font-size:12px;line-height:16px;display:flex}._5i6sLq_noticeIcon{color:var(--dsw-alias-state-warn-label);flex:none}._5i6sLq_linkAction{color:var(--dsw-alias-link);font:inherit;cursor:pointer;background:0 0;border:none;margin:0;padding:0;font-size:12px;text-decoration:underline}._5i6sLq_empty{color:var(--dsw-alias-label-caption);padding:6px 12px;font-size:12px}._5i6sLq_optionsWrapper{padding:4px 12px}._5i6sLq_panelFooter{border-top:.5px solid var(--dsw-alias-border-l2);flex:none;padding:4px 0}._5i6sLq_footerText{color:var(--dsw-alias-label-secondary);padding:5px 12px;font-size:12px;line-height:18px;display:block}._5i6sLq_footerAction{box-sizing:border-box;border-radius:var(--dsw-radius-xs);width:100%;min-height:28px;color:var(--dsw-alias-link);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:4px;padding:4px 12px;font-size:12px;line-height:18px;display:flex}._5i6sLq_footerAction:hover{background:var(--dsw-alias-interactive-bg-hover)}._5i6sLq_footerAction:focus-visible{box-shadow:inset 0 0 0 1.5px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._5i6sLq_footerIcon{flex:none}._5i6sLq_notices{border-top:.5px solid var(--dsw-alias-border-l2);flex:none;padding:4px 0}._5i6sLq_switcher{border-top:.5px solid var(--dsw-alias-border-l2);flex:none;padding:8px}._5i6sLq_tabLabel{align-items:center;gap:4px;min-width:0;display:flex}._5i6sLq_tabTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._5i6sLq_tabMark{flex:none}";
|
|
203
211
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-tool-web-enhanced-ui/src/client/ComposerConnectionMenu.module.css") + "]") === null) {
|
|
204
212
|
const style = document.createElement("style");
|
|
205
213
|
style.dataset.plugin = "dsh-tool-web-enhanced-ui";
|
|
@@ -208,49 +216,53 @@ window.__ModuleLoader__.load({
|
|
|
208
216
|
document.head.appendChild(style);
|
|
209
217
|
}
|
|
210
218
|
var ComposerConnectionMenu_module_css_default = {
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
-
"
|
|
218
|
-
"
|
|
219
|
-
"
|
|
220
|
-
"
|
|
221
|
-
"
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
"
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"
|
|
236
|
-
"
|
|
237
|
-
"
|
|
238
|
-
"
|
|
239
|
-
"notices": "
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
"sideSeparator": "
|
|
244
|
-
"
|
|
245
|
-
"
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
253
|
-
"
|
|
219
|
+
"summary": "_5i6sLq_summary",
|
|
220
|
+
"rowCaption": "_5i6sLq_rowCaption",
|
|
221
|
+
"routeNotice": "_5i6sLq_routeNotice",
|
|
222
|
+
"noticeIcon": "_5i6sLq_noticeIcon",
|
|
223
|
+
"root": "_5i6sLq_root",
|
|
224
|
+
"check": "_5i6sLq_check",
|
|
225
|
+
"panelHeader": "_5i6sLq_panelHeader",
|
|
226
|
+
"trigger": "_5i6sLq_trigger",
|
|
227
|
+
"icon": "_5i6sLq_icon",
|
|
228
|
+
"rowLabel": "_5i6sLq_rowLabel",
|
|
229
|
+
"optionsWrapper": "_5i6sLq_optionsWrapper",
|
|
230
|
+
"warnDot": "_5i6sLq_warnDot",
|
|
231
|
+
"footerText": "_5i6sLq_footerText",
|
|
232
|
+
"footerAction": "_5i6sLq_footerAction",
|
|
233
|
+
"summarySource": "_5i6sLq_summarySource",
|
|
234
|
+
"side": "_5i6sLq_side",
|
|
235
|
+
"chevron": "_5i6sLq_chevron",
|
|
236
|
+
"panelFooter": "_5i6sLq_panelFooter",
|
|
237
|
+
"switcher": "_5i6sLq_switcher",
|
|
238
|
+
"tabMark": "_5i6sLq_tabMark",
|
|
239
|
+
"busy": "_5i6sLq_busy",
|
|
240
|
+
"rowContent": "_5i6sLq_rowContent",
|
|
241
|
+
"chevronOpen": "_5i6sLq_chevronOpen",
|
|
242
|
+
"summarySeparator": "_5i6sLq_summarySeparator",
|
|
243
|
+
"menu": "_5i6sLq_menu",
|
|
244
|
+
"panel": "_5i6sLq_panel",
|
|
245
|
+
"labels": "_5i6sLq_labels",
|
|
246
|
+
"iconMarks": "_5i6sLq_iconMarks",
|
|
247
|
+
"notices": "_5i6sLq_notices",
|
|
248
|
+
"sideLabel": "_5i6sLq_sideLabel",
|
|
249
|
+
"sides": "_5i6sLq_sides",
|
|
250
|
+
"sideMark": "_5i6sLq_sideMark",
|
|
251
|
+
"sideSeparator": "_5i6sLq_sideSeparator",
|
|
252
|
+
"summaryCurrent": "_5i6sLq_summaryCurrent",
|
|
253
|
+
"rowCaptionWarn": "_5i6sLq_rowCaptionWarn",
|
|
254
|
+
"empty": "_5i6sLq_empty",
|
|
255
|
+
"linkAction": "_5i6sLq_linkAction",
|
|
256
|
+
"panelBody": "_5i6sLq_panelBody",
|
|
257
|
+
"panelInactive": "_5i6sLq_panelInactive",
|
|
258
|
+
"settingsButton": "_5i6sLq_settingsButton",
|
|
259
|
+
"disabledNotice": "_5i6sLq_disabledNotice",
|
|
260
|
+
"tabLabel": "_5i6sLq_tabLabel",
|
|
261
|
+
"panels": "_5i6sLq_panels",
|
|
262
|
+
"tabTitle": "_5i6sLq_tabTitle",
|
|
263
|
+
"iconMark": "_5i6sLq_iconMark",
|
|
264
|
+
"footerIcon": "_5i6sLq_footerIcon",
|
|
265
|
+
"row": "_5i6sLq_row"
|
|
254
266
|
};
|
|
255
267
|
//#endregion
|
|
256
268
|
//#region src/client/ComposerConnectionMenu.tsx
|
|
@@ -621,6 +633,7 @@ window.__ModuleLoader__.load({
|
|
|
621
633
|
function SectionPanel({ section, route, sessionId, active, tabId, panelId, onChoose, onCloseMenu, t }) {
|
|
622
634
|
const state = useObservable(section.selection.source(sessionId));
|
|
623
635
|
const settingsFn = useObservable(section.settings);
|
|
636
|
+
const remoteServicesOff = useObservable(section.remoteServicesOff);
|
|
624
637
|
const bodyRef = (0, react.useRef)(null);
|
|
625
638
|
const view = state.view;
|
|
626
639
|
const loaded = view !== void 0;
|
|
@@ -631,6 +644,7 @@ window.__ModuleLoader__.load({
|
|
|
631
644
|
const current = sideText(sideState(section, state), t);
|
|
632
645
|
const source = view !== void 0 && state.readFailure === void 0 ? section.sourceText(view) : "";
|
|
633
646
|
const summaryId = panelId + "-summary";
|
|
647
|
+
const listed = view === void 0 ? [] : view.connections.filter((conn) => conn.status !== "disabled" || conn.id === view.selection.connectionId);
|
|
634
648
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
635
649
|
role: "tabpanel",
|
|
636
650
|
id: panelId,
|
|
@@ -638,137 +652,159 @@ window.__ModuleLoader__.load({
|
|
|
638
652
|
"aria-describedby": summaryId,
|
|
639
653
|
"aria-hidden": active ? void 0 : true,
|
|
640
654
|
className: clsx(ComposerConnectionMenu_module_css_default.panel, !active && ComposerConnectionMenu_module_css_default.panelInactive),
|
|
641
|
-
children: [
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
className: ComposerConnectionMenu_module_css_default.
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
children:
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
"aria-checked": view.selection.connectionId === null,
|
|
707
|
-
className: ComposerConnectionMenu_module_css_default.row,
|
|
708
|
-
disabled: state.saving,
|
|
709
|
-
onClick: () => onChoose(null),
|
|
710
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
711
|
-
className: ComposerConnectionMenu_module_css_default.rowLabel,
|
|
712
|
-
children: t("menu.offRow")
|
|
713
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
714
|
-
className: ComposerConnectionMenu_module_css_default.check,
|
|
715
|
-
children: view.selection.connectionId === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 14 })
|
|
716
|
-
})]
|
|
717
|
-
}), view.connections.map((conn) => {
|
|
718
|
-
const text = section.describe(conn);
|
|
719
|
-
const isSelected = conn.id === view.selection.connectionId;
|
|
720
|
-
const isReady = conn.status === "ready";
|
|
721
|
-
const canOpenSettings = !isReady && settingsFn !== void 0;
|
|
722
|
-
const onClick = () => {
|
|
723
|
-
if (canOpenSettings) {
|
|
724
|
-
onCloseMenu();
|
|
725
|
-
settingsFn();
|
|
726
|
-
} else if (isReady) onChoose(conn.id);
|
|
727
|
-
};
|
|
728
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
655
|
+
children: [
|
|
656
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
657
|
+
className: ComposerConnectionMenu_module_css_default.panelHeader,
|
|
658
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
659
|
+
id: summaryId,
|
|
660
|
+
className: ComposerConnectionMenu_module_css_default.summary,
|
|
661
|
+
title: [current, source].filter(Boolean).join(" · "),
|
|
662
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
663
|
+
className: ComposerConnectionMenu_module_css_default.summaryCurrent,
|
|
664
|
+
children: current
|
|
665
|
+
}), source && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
666
|
+
className: ComposerConnectionMenu_module_css_default.summarySeparator,
|
|
667
|
+
"aria-hidden": "true",
|
|
668
|
+
children: "·"
|
|
669
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
670
|
+
className: ComposerConnectionMenu_module_css_default.summarySource,
|
|
671
|
+
children: source
|
|
672
|
+
})] })]
|
|
673
|
+
}), settingsFn !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
674
|
+
type: "button",
|
|
675
|
+
className: ComposerConnectionMenu_module_css_default.settingsButton,
|
|
676
|
+
"aria-label": t("menu.settings"),
|
|
677
|
+
title: t("menu.settings"),
|
|
678
|
+
onClick: () => {
|
|
679
|
+
onCloseMenu();
|
|
680
|
+
settingsFn();
|
|
681
|
+
},
|
|
682
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutlineRegular, { size: 14 })
|
|
683
|
+
})]
|
|
684
|
+
}),
|
|
685
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
686
|
+
ref: bodyRef,
|
|
687
|
+
className: ComposerConnectionMenu_module_css_default.panelBody,
|
|
688
|
+
children: [route.kind === "other" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
689
|
+
className: ComposerConnectionMenu_module_css_default.routeNotice,
|
|
690
|
+
role: "alert",
|
|
691
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutlineRegular, {
|
|
692
|
+
size: 14,
|
|
693
|
+
className: ComposerConnectionMenu_module_css_default.noticeIcon
|
|
694
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("menu.routeWarning", { provider: route.provider }) })]
|
|
695
|
+
}), state.readFailure === "invalid-settings" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
696
|
+
className: ComposerConnectionMenu_module_css_default.routeNotice,
|
|
697
|
+
role: "alert",
|
|
698
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutlineRegular, {
|
|
699
|
+
size: 14,
|
|
700
|
+
className: ComposerConnectionMenu_module_css_default.noticeIcon
|
|
701
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("menu.invalidSettings", { capability: section.title() }) })]
|
|
702
|
+
}) : view === void 0 ? state.readFailure === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
703
|
+
type: "button",
|
|
704
|
+
className: ComposerConnectionMenu_module_css_default.row,
|
|
705
|
+
onClick: () => {
|
|
706
|
+
section.selection.load(sessionId);
|
|
707
|
+
},
|
|
708
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
709
|
+
className: clsx(ComposerConnectionMenu_module_css_default.rowLabel, ComposerConnectionMenu_module_css_default.rowCaptionWarn),
|
|
710
|
+
children: t("button.readFailed")
|
|
711
|
+
})
|
|
712
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
713
|
+
className: ComposerConnectionMenu_module_css_default.empty,
|
|
714
|
+
children: t("button.loading")
|
|
715
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
716
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
717
|
+
role: "menu",
|
|
718
|
+
"aria-label": section.title(),
|
|
719
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
729
720
|
type: "button",
|
|
730
721
|
role: "menuitemradio",
|
|
731
|
-
"aria-checked":
|
|
722
|
+
"aria-checked": view.selection.connectionId === null,
|
|
732
723
|
className: ComposerConnectionMenu_module_css_default.row,
|
|
733
|
-
disabled:
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
children: [
|
|
739
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
740
|
-
className: ComposerConnectionMenu_module_css_default.rowLabel,
|
|
741
|
-
children: text.label
|
|
742
|
-
}),
|
|
743
|
-
text.caption && !text.reason && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
744
|
-
className: ComposerConnectionMenu_module_css_default.rowCaption,
|
|
745
|
-
children: text.caption
|
|
746
|
-
}),
|
|
747
|
-
text.reason && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
748
|
-
className: clsx(ComposerConnectionMenu_module_css_default.rowCaption, ComposerConnectionMenu_module_css_default.rowCaptionWarn),
|
|
749
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
750
|
-
className: ComposerConnectionMenu_module_css_default.warnDot,
|
|
751
|
-
"aria-hidden": "true"
|
|
752
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text.reason })]
|
|
753
|
-
})
|
|
754
|
-
]
|
|
724
|
+
disabled: state.saving,
|
|
725
|
+
onClick: () => onChoose(null),
|
|
726
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
727
|
+
className: ComposerConnectionMenu_module_css_default.rowLabel,
|
|
728
|
+
children: t("menu.offRow")
|
|
755
729
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
756
730
|
className: ComposerConnectionMenu_module_css_default.check,
|
|
757
|
-
children:
|
|
731
|
+
children: view.selection.connectionId === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 14 })
|
|
758
732
|
})]
|
|
759
|
-
}, conn
|
|
733
|
+
}), listed.map((conn) => {
|
|
734
|
+
const text = section.describe(conn);
|
|
735
|
+
const isSelected = conn.id === view.selection.connectionId;
|
|
736
|
+
const isReady = conn.status === "ready";
|
|
737
|
+
const canOpenSettings = !isReady && settingsFn !== void 0;
|
|
738
|
+
const onClick = () => {
|
|
739
|
+
if (canOpenSettings) {
|
|
740
|
+
onCloseMenu();
|
|
741
|
+
settingsFn();
|
|
742
|
+
} else if (isReady) onChoose(conn.id);
|
|
743
|
+
};
|
|
744
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
745
|
+
type: "button",
|
|
746
|
+
role: "menuitemradio",
|
|
747
|
+
"aria-checked": isSelected,
|
|
748
|
+
className: ComposerConnectionMenu_module_css_default.row,
|
|
749
|
+
disabled: isReady ? state.saving : !canOpenSettings,
|
|
750
|
+
title: text.reason ?? text.label,
|
|
751
|
+
onClick,
|
|
752
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
753
|
+
className: ComposerConnectionMenu_module_css_default.rowContent,
|
|
754
|
+
children: [
|
|
755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
756
|
+
className: ComposerConnectionMenu_module_css_default.rowLabel,
|
|
757
|
+
children: text.label
|
|
758
|
+
}),
|
|
759
|
+
text.caption && !text.reason && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
760
|
+
className: ComposerConnectionMenu_module_css_default.rowCaption,
|
|
761
|
+
children: text.caption
|
|
762
|
+
}),
|
|
763
|
+
text.reason && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
764
|
+
className: clsx(ComposerConnectionMenu_module_css_default.rowCaption, ComposerConnectionMenu_module_css_default.rowCaptionWarn),
|
|
765
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
766
|
+
className: ComposerConnectionMenu_module_css_default.warnDot,
|
|
767
|
+
"aria-hidden": "true"
|
|
768
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text.reason })]
|
|
769
|
+
})
|
|
770
|
+
]
|
|
771
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
772
|
+
className: ComposerConnectionMenu_module_css_default.check,
|
|
773
|
+
children: isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 14 })
|
|
774
|
+
})]
|
|
775
|
+
}, conn.id);
|
|
776
|
+
})]
|
|
777
|
+
}),
|
|
778
|
+
listed.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
779
|
+
className: ComposerConnectionMenu_module_css_default.empty,
|
|
780
|
+
children: t("menu.empty")
|
|
781
|
+
}),
|
|
782
|
+
section.Options && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
783
|
+
className: ComposerConnectionMenu_module_css_default.optionsWrapper,
|
|
784
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(section.Options, { sessionId })
|
|
785
|
+
})
|
|
786
|
+
] })]
|
|
787
|
+
}),
|
|
788
|
+
remoteServicesOff && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
789
|
+
className: ComposerConnectionMenu_module_css_default.panelFooter,
|
|
790
|
+
children: settingsFn === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
791
|
+
className: ComposerConnectionMenu_module_css_default.footerText,
|
|
792
|
+
children: t("menu.moreServices")
|
|
793
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
794
|
+
type: "button",
|
|
795
|
+
className: ComposerConnectionMenu_module_css_default.footerAction,
|
|
796
|
+
onClick: () => {
|
|
797
|
+
onCloseMenu();
|
|
798
|
+
settingsFn();
|
|
799
|
+
},
|
|
800
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("menu.moreServices") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {
|
|
801
|
+
size: 12,
|
|
802
|
+
className: ComposerConnectionMenu_module_css_default.footerIcon,
|
|
803
|
+
"aria-hidden": "true"
|
|
760
804
|
})]
|
|
761
|
-
}),
|
|
762
|
-
view.connections.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
763
|
-
className: ComposerConnectionMenu_module_css_default.empty,
|
|
764
|
-
children: t("menu.empty")
|
|
765
|
-
}),
|
|
766
|
-
section.Options && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
767
|
-
className: ComposerConnectionMenu_module_css_default.optionsWrapper,
|
|
768
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(section.Options, { sessionId })
|
|
769
805
|
})
|
|
770
|
-
|
|
771
|
-
|
|
806
|
+
})
|
|
807
|
+
]
|
|
772
808
|
});
|
|
773
809
|
}
|
|
774
810
|
//#endregion
|
|
@@ -792,11 +828,13 @@ window.__ModuleLoader__.load({
|
|
|
792
828
|
"menu.settings": "设置",
|
|
793
829
|
"menu.routeWarning": "当前由 {provider} 提供,这里的选择不会生效。",
|
|
794
830
|
"menu.invalidSettings": "{capability}的设置无效,请打开设置修复。",
|
|
831
|
+
"menu.moreServices": "更多服务可在设置中打开",
|
|
795
832
|
"disabled.search": "网页搜索暂不可用:增强网页搜索已停用,请在上方启用。",
|
|
796
833
|
"disabled.fetch": "网页获取暂不可用:增强网页获取已停用,请在上方启用。",
|
|
797
834
|
"disabled.openPlugins": "打开插件页",
|
|
798
835
|
"activation.title": "增强网页工具已启用",
|
|
799
836
|
"activation.body": "网页搜索和网页获取现在由本组合包的插件提供。点输入框右侧的地球按钮为每个会话选择连接;连接、密钥和默认值在插件设置里配置。",
|
|
837
|
+
"activation.remoteOff": "远程服务默认关闭,需要时也在那里打开。",
|
|
800
838
|
"activation.preflight": "之前的设置可能让本组合包无法接管网页工具。请打开设置查看详情,并按提示移除遗留设置。",
|
|
801
839
|
"activation.later": "稍后",
|
|
802
840
|
"activation.open": "打开设置",
|
|
@@ -848,11 +886,13 @@ window.__ModuleLoader__.load({
|
|
|
848
886
|
"menu.settings": "Settings",
|
|
849
887
|
"menu.routeWarning": "Served by {provider}; choices here have no effect.",
|
|
850
888
|
"menu.invalidSettings": "{capability} settings are invalid. Open settings to fix them.",
|
|
889
|
+
"menu.moreServices": "More services can be turned on in settings",
|
|
851
890
|
"disabled.search": "Web search isn't available because Web Search Enhanced is off. Turn it on above.",
|
|
852
891
|
"disabled.fetch": "Web fetch isn't available because Web Fetch Enhanced is off. Turn it on above.",
|
|
853
892
|
"disabled.openPlugins": "Open Plugins page",
|
|
854
893
|
"activation.title": "Web Tools Enhanced is enabled",
|
|
855
894
|
"activation.body": "Web search and web fetch now go through this bundle's plugins. Pick a connection for each conversation with the globe button in the composer; set up connections, keys and defaults in the plugin settings.",
|
|
895
|
+
"activation.remoteOff": "Remote services are off by default; turn them on there when you need them.",
|
|
856
896
|
"activation.preflight": "Some previous settings may stop this bundle from handling web tools. Open settings to review them and remove leftover settings.",
|
|
857
897
|
"activation.later": "Later",
|
|
858
898
|
"activation.open": "Open settings",
|
|
@@ -887,8 +927,8 @@ window.__ModuleLoader__.load({
|
|
|
887
927
|
"preflight.action.failed": "Not changed. The settings may have changed elsewhere; try again."
|
|
888
928
|
};
|
|
889
929
|
//#endregion
|
|
890
|
-
//#region \0dsh-css-module:/
|
|
891
|
-
const css = ".
|
|
930
|
+
//#region \0dsh-css-module:/home/runner/work/dsh-tool-web-enhanced/dsh-tool-web-enhanced/packages/ui/src/client/ProfileDetailSection.module.css.mjs
|
|
931
|
+
const css = ".qKxLyW_section{flex-direction:column;gap:12px;margin-top:24px;display:flex}.qKxLyW_header{flex-direction:column;gap:2px;display:flex}.qKxLyW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:500;line-height:20px}.qKxLyW_description{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:18px}.qKxLyW_container{flex-direction:column;display:flex}.qKxLyW_card{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:12px 2px;display:flex}.qKxLyW_cardHeader{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;display:flex}.qKxLyW_cardTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:500;line-height:20px}.qKxLyW_statusList{color:var(--dsw-alias-label-secondary);flex-direction:column;gap:4px;font-size:12px;line-height:16px;display:flex}.qKxLyW_statusItem{align-items:baseline;gap:6px;display:flex}.qKxLyW_statusItem code,.qKxLyW_issueItem code{border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-bg-module-platform);font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);color:var(--dsw-alias-label-primary);padding:1px 4px;font-size:11.5px}.qKxLyW_routedBadge,.qKxLyW_notRoutedBadge{white-space:nowrap;color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:12px;font-weight:400;line-height:16px;display:inline-flex}.qKxLyW_preflightBox{flex-direction:column;gap:10px;padding:12px 2px;display:flex}.qKxLyW_preflightHeader{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;display:flex}.qKxLyW_preflightTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:500;line-height:20px}.qKxLyW_healthyText{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:18px}.qKxLyW_issuesList{flex-direction:column;gap:8px;display:flex}.qKxLyW_issueItem{color:var(--dsw-alias-label-secondary);align-items:flex-start;gap:8px;font-size:13px;line-height:18px;display:flex}.qKxLyW_issueIcon{color:var(--dsw-alias-state-warn-label);flex:0 0 16px;margin-top:1px}.qKxLyW_fixableActionRow{align-items:center;margin-top:6px;display:flex}.qKxLyW_warnBox{border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-label-secondary);border:.5px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 30%, transparent);align-items:flex-start;gap:8px;padding:8px 10px;font-size:12px;line-height:16px;display:flex}.qKxLyW_warnIcon{color:var(--dsw-alias-state-warn-label);flex:none}";
|
|
892
932
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-tool-web-enhanced-ui/src/client/ProfileDetailSection.module.css") + "]") === null) {
|
|
893
933
|
const style = document.createElement("style");
|
|
894
934
|
style.dataset.plugin = "dsh-tool-web-enhanced-ui";
|
|
@@ -897,28 +937,28 @@ window.__ModuleLoader__.load({
|
|
|
897
937
|
document.head.appendChild(style);
|
|
898
938
|
}
|
|
899
939
|
var ProfileDetailSection_module_css_default = {
|
|
900
|
-
"
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
"
|
|
904
|
-
"
|
|
905
|
-
"
|
|
906
|
-
"
|
|
907
|
-
"
|
|
908
|
-
"
|
|
909
|
-
"
|
|
910
|
-
"description": "
|
|
911
|
-
"
|
|
912
|
-
"
|
|
913
|
-
"
|
|
914
|
-
"
|
|
915
|
-
"
|
|
916
|
-
"
|
|
917
|
-
"
|
|
918
|
-
"
|
|
919
|
-
"
|
|
920
|
-
"
|
|
921
|
-
"
|
|
940
|
+
"statusList": "qKxLyW_statusList",
|
|
941
|
+
"warnIcon": "qKxLyW_warnIcon",
|
|
942
|
+
"healthyText": "qKxLyW_healthyText",
|
|
943
|
+
"container": "qKxLyW_container",
|
|
944
|
+
"cardTitle": "qKxLyW_cardTitle",
|
|
945
|
+
"preflightBox": "qKxLyW_preflightBox",
|
|
946
|
+
"section": "qKxLyW_section",
|
|
947
|
+
"cardHeader": "qKxLyW_cardHeader",
|
|
948
|
+
"notRoutedBadge": "qKxLyW_notRoutedBadge",
|
|
949
|
+
"routedBadge": "qKxLyW_routedBadge",
|
|
950
|
+
"description": "qKxLyW_description",
|
|
951
|
+
"issueIcon": "qKxLyW_issueIcon",
|
|
952
|
+
"fixableActionRow": "qKxLyW_fixableActionRow",
|
|
953
|
+
"title": "qKxLyW_title",
|
|
954
|
+
"header": "qKxLyW_header",
|
|
955
|
+
"issueItem": "qKxLyW_issueItem",
|
|
956
|
+
"preflightTitle": "qKxLyW_preflightTitle",
|
|
957
|
+
"card": "qKxLyW_card",
|
|
958
|
+
"issuesList": "qKxLyW_issuesList",
|
|
959
|
+
"statusItem": "qKxLyW_statusItem",
|
|
960
|
+
"preflightHeader": "qKxLyW_preflightHeader",
|
|
961
|
+
"warnBox": "qKxLyW_warnBox"
|
|
922
962
|
};
|
|
923
963
|
//#endregion
|
|
924
964
|
//#region src/client/ProfileDetailSection.tsx
|
package/lib/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.cjs","names":["useCallback","useSyncExternalStore","Modal","Button","useState","useRef","useId","useMemo","css","StateDot","IconGlobeOutlineRegular","Fragment","IconChevronDownOutlineRegular","createPortal","MenuSurface","IconWarningOutlineRegular","SegmentedTabs","Toast","IconSettingsOutlineRegular","IconCheckOutlineRegular","useState","css","IconWarningOutlineRegular","Button","Modal","Toast","IconCheckOutlineRegular","StateDot","createSnapshotStore","createSnapshotStore"],"sources":["../../core/src/shared/ids.ts","../../core/src/shared/route.ts","../../core/src/client/use-observable.ts","../src/client/preflight.ts","../src/client/ActivationPrompt.tsx","../src/client/disabled.ts","../src/client/ComposerConnectionMenu.tsx","../src/client/locales.ts","../src/client/ProfileDetailSection.tsx","../src/client/service.ts","../src/client/index.tsx"],"sourcesContent":["/**\n * Identities that bind the profile bundle, its rows, and both faces together.\n * The profile's patch writes these ids, the plugins register them, and the\n * browser faces key their slots by them; tests assert all three agree.\n * Nothing here imports Node, the browser, or a Host package.\n */\n\n/** npm name of the profile bundle users install; the Plugins page keys bundle and row pages by it. */\nexport const PROFILE_PACKAGE = 'dsh-tool-web-enhanced-profile'\n\n/** A package the profile mounts as one row. */\nexport interface RowIdentity {\n /** npm package name; the profile bundle depends on it and names it in its row. */\n readonly packageName: string\n /** Row id the profile patch inserts; also the Settings namespace and the Cordis plugin name. */\n readonly rowId: string\n}\n\n/** A row that serves one web capability. */\nexport interface PluginIdentity extends RowIdentity {\n /** Provider id registered in `ctx.web`; the profile writes it into the `web` row. */\n readonly providerId: string\n}\n\nexport const SEARCH: PluginIdentity = {\n packageName: 'dsh-web-search-enhanced',\n rowId: 'web-search-enhanced',\n providerId: 'search-enhanced',\n}\n\nexport const FETCH: PluginIdentity = {\n packageName: 'dsh-web-fetch-enhanced',\n rowId: 'web-fetch-enhanced',\n providerId: 'fetch-enhanced',\n}\n\n/** The browser-only row holding the shared composer connection menu. */\nexport const UI: RowIdentity = {\n packageName: 'dsh-tool-web-enhanced-ui',\n rowId: 'tool-web-enhanced-ui',\n}\n\n/**\n * Key of a row's configuration page on the Plugins page (`plugins.row.config`).\n * @param row - the row the page configures.\n * @returns `<profile package>#<row id>`.\n */\nexport function rowConfigKey(row: RowIdentity): string {\n return `${PROFILE_PACKAGE}#${row.rowId}`\n}\n","/**\n * Whether the shared `web` row routes a capability to this plugin, judged the\n * way `WebRuntime` selects: the row's field, else the process environment\n * variable, else auto-selection. The Host reads the row through the public\n * Settings data; the browser reads it through `configForms.get('web')`. When\n * the row cannot be read, the answer is `unknown` and callers treat it as\n * \"not routed\".\n */\n\nexport type Route =\n /** The `web` row is not readable, or the Host has not answered yet. */\n | { readonly kind: 'unknown' }\n | { readonly kind: 'this' }\n /** Nothing pins a provider: `WebRuntime` auto-selects and fails while several are usable. */\n | { readonly kind: 'auto'; readonly providerId: string }\n /** Another provider serves the capability, so this plugin's settings have no effect. */\n | { readonly kind: 'other'; readonly provider: string; readonly providerId: string }\n\n/** The two `web` row fields and the environment variables `WebRuntime` reads instead. */\nexport const WEB_ROW = 'web'\nexport const WEB_FIELD = { search: 'searchProvider', fetch: 'fetchProvider' } as const\nexport const WEB_ENV = { search: 'DSH_WEB_SEARCH_PROVIDER', fetch: 'DSH_WEB_FETCH_PROVIDER' } as const\n\n/**\n * @param row - the `web` row's effective value, or undefined when it cannot be read.\n * @param field - which capability's field to judge.\n * @param envProvider - the process variable of that capability, or null when unset.\n * @param providerId - the id this plugin registered.\n */\nexport function routeOf(row: Readonly<Record<string, unknown>> | undefined, field: string, envProvider: string | null, providerId: string): Route {\n if (row === undefined) return { kind: 'unknown' }\n const configured = row[field]\n // Like `WebRuntime` (`config.searchProvider.get() ?? env`): only an absent field falls back to the variable.\n const pinned = typeof configured === 'string' ? configured : envProvider\n if (pinned === null) return { kind: 'auto', providerId }\n return pinned === providerId ? { kind: 'this' } : { kind: 'other', provider: pinned, providerId }\n}\n\n/** Whether the capability reaches this plugin; `unknown` and `auto` count as not routed. */\nexport const isRouted = (route: Route): boolean => route.kind === 'this'\n","import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport { useCallback, useSyncExternalStore } from 'react'\n\n/**\n * Read an observable snapshot in a component. The subscribe and getSnapshot\n * callbacks are stable per source, so React subscribes once per source rather\n * than once per render; a source that publishes on subscription would\n * otherwise re-render and re-subscribe without end.\n */\nexport function useObservable<T>(source: ObservableSnapshot<T>): T {\n const subscribe = useCallback((listener: () => void) => source.subscribe(listener), [source])\n const getSnapshot = useCallback(() => source.getSnapshot(), [source])\n return useSyncExternalStore(subscribe, getSnapshot)\n}\n","import { FETCH, SEARCH } from 'dsh-tool-web-enhanced-core/shared'\nimport type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client'\n\nexport const NATIVE_SEARCH_PROVIDERS: readonly string[] = [\n 'deepseek-official',\n 'deepseek-search-api',\n]\nexport const NATIVE_FETCH_PROVIDERS: readonly string[] = [\n 'http',\n 'deepseek-fetch-api',\n]\nexport const NATIVE_SEARCH_ROW = 'web-search-deepseek'\n\nexport type PreflightIssueKind =\n | 'user-override'\n | 'legacy-remnant'\n | 'native-search-conflict'\n\nexport type PreflightIssue =\n | {\n readonly kind: 'user-override'\n readonly field: 'searchProvider' | 'fetchProvider'\n readonly value: string\n }\n | {\n readonly kind: 'legacy-remnant'\n readonly field: 'searchProvider' | 'fetchProvider'\n readonly value: string\n }\n | {\n readonly kind: 'native-search-conflict'\n readonly rowId: string\n }\n\nexport interface UpgradePreflightResult {\n readonly issues: readonly PreflightIssue[]\n readonly fieldsToUnset: readonly ('searchProvider' | 'fetchProvider')[]\n}\n\n/**\n * Pure function to inspect settings and determine upgrade preflight issues (§11).\n */\nexport function checkUpgradePreflight(params: {\n readonly user?: unknown\n readonly nativeSearchServed: boolean\n}): UpgradePreflightResult {\n const issues: PreflightIssue[] = []\n const fieldsToUnset: ('searchProvider' | 'fetchProvider')[] = []\n\n const user =\n typeof params.user === 'object' && params.user !== null\n ? (params.user as Record<string, unknown>)\n : undefined\n\n if (user !== undefined) {\n if ('searchProvider' in user && typeof user.searchProvider === 'string') {\n const val = user.searchProvider\n if (val !== SEARCH.providerId) {\n fieldsToUnset.push('searchProvider')\n if (NATIVE_SEARCH_PROVIDERS.includes(val)) {\n issues.push({\n kind: 'user-override',\n field: 'searchProvider',\n value: val,\n })\n } else {\n issues.push({\n kind: 'legacy-remnant',\n field: 'searchProvider',\n value: val,\n })\n }\n }\n }\n\n if ('fetchProvider' in user && typeof user.fetchProvider === 'string') {\n const val = user.fetchProvider\n if (val !== FETCH.providerId) {\n fieldsToUnset.push('fetchProvider')\n if (NATIVE_FETCH_PROVIDERS.includes(val)) {\n issues.push({\n kind: 'user-override',\n field: 'fetchProvider',\n value: val,\n })\n } else {\n issues.push({\n kind: 'legacy-remnant',\n field: 'fetchProvider',\n value: val,\n })\n }\n }\n }\n }\n\n if (params.nativeSearchServed) {\n issues.push({\n kind: 'native-search-conflict',\n rowId: NATIVE_SEARCH_ROW,\n })\n }\n\n return {\n issues,\n fieldsToUnset,\n }\n}\n\n/**\n * Generate SettingsPathOpView array for resetting user-tier overrides on web row.\n */\nexport function buildUnsetOps(\n fields: readonly ('searchProvider' | 'fetchProvider')[],\n): SettingsPathOpView[] {\n return fields.map(field => ({\n op: 'unset',\n path: [field],\n }))\n}\n","import { Button, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PluginActivationOwnerProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { NS } from './locales.ts'\nimport type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { useObservable } from 'dsh-tool-web-enhanced-core/client'\nimport { checkUpgradePreflight } from './preflight.ts'\n\nexport type ActivationPromptProps = PluginActivationOwnerProps & PropsLocale<typeof NS> & {\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n}\n\nexport function ActivationPrompt({ onDismiss, onOpenDetails, webConfigForm, nativeSearchServed, t }: ActivationPromptProps) {\n const web = useObservable(webConfigForm)\n const preflight = checkUpgradePreflight({ user: web.user, nativeSearchServed })\n const hasIssues = preflight.issues.length > 0\n return (\n <Modal\n open\n title={t('activation.title')}\n closeLabel={t('activation.close')}\n onClose={onDismiss}\n footer={\n <>\n <Button variant=\"ghost\" onClick={onDismiss}>\n {t('activation.later')}\n </Button>\n <Button variant=\"primary\" data-modal-autofocus onClick={onOpenDetails}>\n {t('activation.open')}\n </Button>\n </>\n }\n >\n <p>{t(hasIssues ? 'activation.preflight' : 'activation.body')}</p>\n </Modal>\n )\n}\n","import { FETCH, SEARCH, WEB_FIELD, routeOf, type Route } from 'dsh-tool-web-enhanced-core/shared'\nimport type { CapabilityName } from 'dsh-tool-web-enhanced-core/client'\nimport type { PluginRowRef } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\n\nexport interface WebConfigSnapshot {\n readonly [field: string]: unknown\n readonly searchProvider?: unknown\n readonly fetchProvider?: unknown\n}\n\nexport interface DisabledCapabilitiesResult {\n readonly searchDisabled: boolean\n readonly fetchDisabled: boolean\n readonly allDisabled: boolean\n}\n\nconst PROVIDER_ID = { search: SEARCH.providerId, fetch: FETCH.providerId } as const satisfies Record<CapabilityName, string>\n\n/**\n * Where a capability routes: the fact its plugin registered, or, without a\n * running plugin to register one, what the `web` row settings say.\n */\nexport function routeFor(capability: CapabilityName, routes: ReadonlyMap<CapabilityName, Route>, webConfig: WebConfigSnapshot | undefined): Route {\n const registered = routes.get(capability)\n return registered === undefined ? routeOf(webConfig, WEB_FIELD[capability], null, PROVIDER_ID[capability]) : registered\n}\n\n/**\n * Check whether routing targets an enhanced provider whose plugin is not served.\n * Prefer Host-aware facts; an absent plugin can only be judged from the web settings.\n */\nexport function checkDisabledCapabilities(params: {\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly routes: ReadonlyMap<CapabilityName, Route>\n}): DisabledCapabilitiesResult {\n const searchDisabled = routeFor('search', params.routes, params.webConfig).kind === 'this' && !params.searchServed\n const fetchDisabled = routeFor('fetch', params.routes, params.webConfig).kind === 'this' && !params.fetchServed\n\n const allDisabled = searchDisabled && fetchDisabled\n\n return {\n searchDisabled,\n fetchDisabled,\n allDisabled,\n }\n}\n\n/**\n * Pure function to check if a capability row is disabled in the bundle package rows.\n */\nexport function isCapabilityRowDisabled(params: {\n readonly rowId: string\n readonly rows: readonly PluginRowRef[]\n}): boolean {\n const row = params.rows.find(r => r.rowId === params.rowId)\n return row !== undefined && !row.enabled\n}\n","import {\n Fragment,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n IconCheckOutlineRegular,\n IconChevronDownOutlineRegular,\n IconGlobeOutlineRegular,\n IconSettingsOutlineRegular,\n IconWarningOutlineRegular,\n MenuSurface,\n SegmentedTabs,\n StateDot,\n Toast,\n useDismissOnOutsidePointer,\n type SegmentedTab,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport { useObservable, type CapabilityName, type ConnectionSection, type SelectionState, type WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport { checkDisabledCapabilities, routeFor, type WebConfigSnapshot } from './disabled.ts'\nimport type { NS } from './locales.ts'\nimport type { Route } from 'dsh-tool-web-enhanced-core/shared'\nimport css from './ComposerConnectionMenu.module.css'\n\nfunction clsx(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ')\n}\n\nexport type Translate = TranslateNS<typeof NS>\n\n/** What one capability's side of the button and its section heading show. */\ntype SideState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'read-failed' }\n | { readonly kind: 'invalid-settings' }\n | { readonly kind: 'off' }\n | { readonly kind: 'missing' }\n | { readonly kind: 'connection'; readonly label: string; readonly ready: boolean }\n\nfunction sideState(section: ConnectionSection, state: SelectionState): SideState {\n if (state.readFailure === 'invalid-settings') return { kind: 'invalid-settings' }\n if (state.readFailure === 'failed') return { kind: 'read-failed' }\n const { view } = state\n if (view === undefined) return { kind: 'loading' }\n const { connectionId } = view.selection\n if (connectionId === null) return { kind: 'off' }\n const selected = view.connections.find(connection => connection.id === connectionId)\n if (selected === undefined) return { kind: 'missing' }\n return { kind: 'connection', label: section.describe(selected).label, ready: selected.status === 'ready' }\n}\n\nfunction sideText(side: SideState, t: Translate): string {\n switch (side.kind) {\n case 'loading': return t('button.loading')\n case 'read-failed': return t('button.readFailed')\n case 'invalid-settings': return t('button.invalidSettings')\n case 'off': return t('button.off')\n case 'missing': return t('button.missing')\n case 'connection': return side.label\n }\n}\n\n/** Whether the side needs the user: it cannot serve as shown, or the web row sends the capability elsewhere. */\nfunction needsAttention(side: SideState, route: Route): boolean {\n if (route.kind === 'other') return true\n switch (side.kind) {\n case 'loading':\n case 'off': return false\n case 'read-failed':\n case 'invalid-settings':\n case 'missing': return true\n case 'connection': return !side.ready\n }\n}\n\n/** One snapshot of several sources; the array stays the same while none of them changes. */\nfunction combineSnapshots<T>(sources: readonly ObservableSnapshot<T>[]): ObservableSnapshot<readonly T[]> {\n let last: readonly T[] = []\n return {\n getSnapshot() {\n const next = sources.map(source => source.getSnapshot())\n if (next.length !== last.length || next.some((value, index) => value !== last[index])) last = next\n return last\n },\n subscribe(listener) {\n const unsubscribes = sources.map(source => source.subscribe(listener))\n return () => {\n for (const unsubscribe of unsubscribes) unsubscribe()\n }\n },\n }\n}\n\nexport interface ModelSelectionProjection {\n readonly next?: { readonly provider: string; readonly model: string } | undefined\n}\n\nexport function modelKeyOf(projection: ModelSelectionProjection | undefined): string {\n const model = projection?.next\n return model ? `${model.provider}/${model.model}` : ''\n}\n\nfunction useMenuPosition({\n open,\n anchorRef,\n panelRef,\n rootRef,\n}: {\n open: boolean\n anchorRef: React.RefObject<HTMLElement | null>\n panelRef: React.RefObject<HTMLElement | null>\n rootRef: React.RefObject<HTMLElement | null>\n}): { left: number; top: number; maxWidth: number } | null {\n const [rawPosition, setRawPosition] = useState<{ left: number; top: number; maxWidth: number } | null>(null)\n\n useEffect(() => {\n if (!open) return\n\n const place = () => {\n const anchor = anchorRef.current\n if (!anchor) return\n const rect = anchor.getBoundingClientRect()\n const panel = panelRef.current\n const measuredWidth = panel?.offsetWidth ?? 0\n const height = panel?.offsetHeight ?? 0\n\n // Main content area left boundary (e.g. conversation session container)\n const mainArea =\n rootRef.current?.closest('[data-conversation-session]') ??\n document.querySelector('[data-conversation-session]') ??\n document.querySelector('main')\n const mainLeft = mainArea ? mainArea.getBoundingClientRect().left : 12\n const minLeft = Math.min(Math.max(12, mainLeft), window.innerWidth - 12)\n const maxWidth = Math.max(0, window.innerWidth - minLeft - 12)\n const width = Math.min(measuredWidth, maxWidth)\n\n let left = rect.right - width\n // If overflowing left boundary, check if flipping to start fits better\n if (left < minLeft && rect.left + width <= window.innerWidth - 12) {\n left = rect.left\n }\n if (width > 0) {\n const maxLeft = Math.max(minLeft, window.innerWidth - width - 12)\n left = Math.min(Math.max(left, minLeft), maxLeft)\n }\n\n // Vertical placement: side='top', gap=8\n let top = rect.top - 8 - height\n if (top < 12 && rect.bottom + 8 + height <= window.innerHeight - 12) {\n top = rect.bottom + 8\n }\n if (height > 0) {\n top = Math.min(Math.max(top, 12), Math.max(12, window.innerHeight - height - 12))\n }\n\n setRawPosition({ left, top, maxWidth })\n }\n\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n\n let observer: ResizeObserver | null = null\n if (typeof ResizeObserver !== 'undefined' && panelRef.current) {\n observer = new ResizeObserver(place)\n observer.observe(panelRef.current)\n }\n\n return () => {\n observer?.disconnect()\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [open, anchorRef, panelRef, rootRef])\n\n return open ? rawPosition : null\n}\n\nexport interface ComposerConnectionMenuProps {\n readonly sessionId: string\n readonly modelKey?: string | undefined\n readonly webConnections: WebConnectionsService\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly onOpenPlugins?: (() => void) | undefined\n readonly t: Translate\n}\n\nexport function ComposerConnectionMenu({\n sessionId,\n modelKey,\n webConnections,\n searchServed,\n fetchServed,\n webConfig,\n onOpenPlugins,\n t,\n}: ComposerConnectionMenuProps) {\n const sections = useObservable(webConnections.sections)\n const routes = useObservable(webConnections.routes)\n\n if (sections.length === 0) {\n return null\n }\n\n return (\n <ComposerConnectionMenuInner\n sessionId={sessionId}\n modelKey={modelKey}\n sections={sections}\n routes={routes}\n searchServed={searchServed}\n fetchServed={fetchServed}\n webConfig={webConfig}\n onOpenPlugins={onOpenPlugins}\n t={t}\n />\n )\n}\n\nfunction ComposerConnectionMenuInner({\n sessionId,\n modelKey,\n sections,\n routes,\n searchServed,\n fetchServed,\n webConfig,\n onOpenPlugins,\n t,\n}: {\n readonly sessionId: string\n readonly modelKey?: string | undefined\n readonly sections: readonly ConnectionSection[]\n readonly routes: ReadonlyMap<CapabilityName, Route>\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly onOpenPlugins?: (() => void) | undefined\n readonly t: Translate\n}) {\n const [open, setOpen] = useState(false)\n // The capability whose panel the menu shows; the menu opens on the first.\n const [selected, setSelected] = useState<CapabilityName | null>(null)\n const [notice, setNotice] = useState<{ seq: number; text: string } | null>(null)\n const [rootEl, setRootEl] = useState<HTMLDivElement | null>(null)\n const seqRef = useRef(0)\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const id = useId()\n\n const position = useMenuPosition({\n open,\n anchorRef: triggerRef,\n panelRef: menuRef,\n rootRef,\n })\n useDismissOnOutsidePointer(rootRef, open, setOpen, menuRef)\n\n // A dialog takes focus: the selected tab, once the placed menu is visible and focusable.\n const placed = position !== null\n useEffect(() => {\n if (!placed) return\n menuRef.current?.querySelector<HTMLElement>('[role=\"tab\"][aria-selected=\"true\"]')?.focus({ preventScroll: true })\n }, [placed])\n\n const sortedSections = useMemo(() => sections.toSorted((a, b) => a.order - b.order), [sections])\n const states = useObservable(useMemo(\n () => combineSnapshots(sortedSections.map(section => section.selection.source(sessionId))),\n [sortedSections, sessionId],\n ))\n\n useEffect(() => {\n for (const section of sections) {\n void section.selection.load(sessionId, modelKey)\n }\n }, [sections, sessionId, modelKey])\n\n const close = (): void => {\n setOpen(false)\n triggerRef.current?.focus()\n }\n\n const onTriggerClick = (): void => {\n if (open) {\n close()\n } else {\n setOpen(true)\n setSelected(sortedSections[0]!.capability)\n for (const section of sections) {\n void section.selection.load(sessionId, modelKey)\n }\n }\n }\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n if (!open || event.nativeEvent.isComposing) return\n if (event.key === 'Escape') {\n event.preventDefault()\n close()\n }\n }\n\n const choose = async (section: ConnectionSection, connectionId: string | null): Promise<void> => {\n const currentView = section.selection.source(sessionId).getSnapshot().view\n if (currentView?.selection.connectionId === connectionId) {\n close()\n return\n }\n\n const res = await section.selection.set(sessionId, { connectionId })\n if (!res.ok) {\n setNotice({ seq: seqRef.current++, text: section.writeFailureText(res.error) })\n } else {\n close()\n }\n }\n\n // Each side shows its connection; other states name their side, since \"Off\" alone does not say which.\n const sides = sortedSections.map((section, index) => {\n const side = sideState(section, states[index]!)\n const state = sideText(side, t)\n const capability = section.title()\n const attention = needsAttention(side, routeFor(section.capability, routes, webConfig))\n return {\n section,\n capability: section.capability,\n label: side.kind === 'connection' ? state : t('button.side', { capability, state }),\n name: t(attention ? 'button.sideAttention' : 'button.side', { capability, state }),\n attention,\n }\n })\n const triggerName = sides.map(side => side.name).join(' · ')\n const saving = states.some(state => state.saving)\n\n // A section that went away while the menu was open hands the panel to the first.\n const active = sortedSections.find(section => section.capability === selected) ?? sortedSections[0]!\n const tabId = (capability: CapabilityName): string => `${id}-tab-${capability}`\n const panelId = (capability: CapabilityName): string => `${id}-panel-${capability}`\n const [firstTab, ...otherTabs] = sides.map((side): SegmentedTab<CapabilityName> => ({\n value: side.capability,\n id: tabId(side.capability),\n panelId: panelId(side.capability),\n label: (\n <span className={css.tabLabel} title={side.name}>\n <span className={css.tabTitle}>{side.section.title()}</span>\n {side.attention && <StateDot state=\"warning\" className={css.tabMark} />}\n </span>\n ),\n }))\n\n const disabled = checkDisabledCapabilities({\n searchServed,\n fetchServed,\n webConfig,\n routes,\n })\n const unavailable = [\n ...(disabled.searchDisabled ? [t('disabled.search')] : []),\n ...(disabled.fetchDisabled ? [t('disabled.fetch')] : []),\n ]\n\n return (\n <div\n ref={el => {\n rootRef.current = el\n setRootEl(el)\n }}\n className={css.root}\n onKeyDown={onKeyDown}\n >\n <button\n ref={triggerRef}\n type=\"button\"\n className={css.trigger}\n aria-label={triggerName}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? `${id}-menu` : undefined}\n title={triggerName}\n onClick={onTriggerClick}\n >\n <span className={css.icon}>\n <IconGlobeOutlineRegular size={16} />\n {/* The compact display: the labels are hidden, so each side's mark sits on the globe. */}\n <span className={css.iconMarks}>\n {sides.map(side => side.attention && (\n <span key={side.capability} className={css.iconMark} data-mark={side.capability}>\n <StateDot state=\"warning\" />\n </span>\n ))}\n </span>\n </span>\n <span className={css.labels}>\n <span className={css.sides}>\n {sides.map((side, index) => (\n <Fragment key={side.capability}>\n {index > 0 && <span className={css.sideSeparator} aria-hidden=\"true\">·</span>}\n <span className={css.side} data-capability={side.capability}>\n <span className={css.sideLabel}>{side.label}</span>\n {side.attention && <StateDot state=\"warning\" className={css.sideMark} />}\n </span>\n </Fragment>\n ))}\n </span>\n </span>\n {saving ? (\n <StateDot state=\"ongoing\" className={css.busy} />\n ) : (\n <IconChevronDownOutlineRegular\n size={12}\n className={clsx(css.chevron, open && css.chevronOpen)}\n />\n )}\n </button>\n\n {open &&\n createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={css.menu}\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n aria-label={t('menu.aria')}\n >\n {/* Every panel shares one grid cell: the menu keeps the tallest one's height while switching. */}\n <div className={css.panels}>\n {sortedSections.map(section => (\n <SectionPanel\n key={section.capability}\n section={section}\n route={routeFor(section.capability, routes, webConfig)}\n sessionId={sessionId}\n active={section === active}\n tabId={tabId(section.capability)}\n panelId={panelId(section.capability)}\n onChoose={connId => void choose(section, connId)}\n onCloseMenu={close}\n t={t}\n />\n ))}\n </div>\n\n {unavailable.length > 0 && (\n <div className={css.notices}>\n {unavailable.map(text => (\n <div key={text} className={css.disabledNotice} role=\"status\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <div>\n <div>{text}</div>\n {onOpenPlugins !== undefined && (\n <button\n type=\"button\"\n className={css.linkAction}\n onClick={() => {\n close()\n onOpenPlugins()\n }}\n >\n {t('disabled.openPlugins')}\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* The bottom layer, nearest the button: which capability the panel above shows. */}\n <div className={css.switcher}>\n <SegmentedTabs\n items={[firstTab!, ...otherTabs]}\n value={active.capability}\n onChange={setSelected}\n label={t('menu.tabs')}\n />\n </div>\n </MenuSurface>,\n document.body,\n )}\n\n {notice !== null && (\n <Toast\n key={notice.seq}\n text={notice.text}\n icon={<IconWarningOutlineRegular />}\n holdMs={4000}\n anchor={rootEl}\n onDone={() => setNotice(null)}\n />\n )}\n </div>\n )\n}\n\nfunction SectionPanel({\n section,\n route,\n sessionId,\n active,\n tabId,\n panelId,\n onChoose,\n onCloseMenu,\n t,\n}: {\n readonly section: ConnectionSection\n readonly route: Route\n readonly sessionId: string\n readonly active: boolean\n readonly tabId: string\n readonly panelId: string\n readonly onChoose: (connectionId: string | null) => void\n readonly onCloseMenu: () => void\n readonly t: Translate\n}) {\n const state = useObservable(section.selection.source(sessionId))\n const settingsFn = useObservable(section.settings)\n const bodyRef = useRef<HTMLDivElement | null>(null)\n\n const view = state.view\n const loaded = view !== undefined\n\n // Showing a panel, or its list arriving while shown, brings the chosen row into view.\n useEffect(() => {\n if (!active || !loaded) return\n bodyRef.current?.querySelector('[aria-checked=\"true\"]')?.scrollIntoView({ block: 'nearest' })\n }, [active, loaded])\n\n const current = sideText(sideState(section, state), t)\n // A failed read leaves no current source to name.\n const source = view !== undefined && state.readFailure === undefined ? section.sourceText(view) : ''\n const summaryId = panelId + '-summary'\n\n return (\n <div\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-describedby={summaryId}\n // Hidden panels keep their size so the menu does not jump; they leave the tab order and the accessibility tree.\n aria-hidden={active ? undefined : true}\n className={clsx(css.panel, !active && css.panelInactive)}\n >\n <div className={css.panelHeader}>\n <p id={summaryId} className={css.summary} title={[current, source].filter(Boolean).join(' · ')}>\n <span className={css.summaryCurrent}>{current}</span>\n {source && (\n <>\n <span className={css.summarySeparator} aria-hidden=\"true\">·</span>\n <span className={css.summarySource}>{source}</span>\n </>\n )}\n </p>\n {/* An icon, so the summary keeps the header's width. */}\n {settingsFn !== undefined && (\n <button\n type=\"button\"\n className={css.settingsButton}\n aria-label={t('menu.settings')}\n title={t('menu.settings')}\n onClick={() => {\n onCloseMenu()\n settingsFn()\n }}\n >\n <IconSettingsOutlineRegular size={14} />\n </button>\n )}\n </div>\n\n <div ref={bodyRef} className={css.panelBody}>\n {route.kind === 'other' && (\n <div className={css.routeNotice} role=\"alert\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <span>{t('menu.routeWarning', { provider: route.provider })}</span>\n </div>\n )}\n\n {state.readFailure === 'invalid-settings' ? (\n // Retrying cannot help: the settings must be fixed, through the settings entry above.\n <div className={css.routeNotice} role=\"alert\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <span>{t('menu.invalidSettings', { capability: section.title() })}</span>\n </div>\n ) : view === undefined ? (\n state.readFailure === 'failed' ? (\n <button\n type=\"button\"\n className={css.row}\n onClick={() => {\n void section.selection.load(sessionId)\n }}\n >\n <span className={clsx(css.rowLabel, css.rowCaptionWarn)}>\n {t('button.readFailed')}\n </span>\n </button>\n ) : (\n <div className={css.empty}>{t('button.loading')}</div>\n )\n ) : (\n <>\n <div role=\"menu\" aria-label={section.title()}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={view.selection.connectionId === null}\n className={css.row}\n disabled={state.saving}\n onClick={() => onChoose(null)}\n >\n <span className={css.rowLabel}>{t('menu.offRow')}</span>\n <span className={css.check}>\n {view.selection.connectionId === null && <IconCheckOutlineRegular size={14} />}\n </span>\n </button>\n\n {view.connections.map(conn => {\n const text = section.describe(conn)\n const isSelected = conn.id === view.selection.connectionId\n const isReady = conn.status === 'ready'\n const canOpenSettings = !isReady && settingsFn !== undefined\n\n const onClick = () => {\n if (canOpenSettings) {\n onCloseMenu()\n settingsFn()\n } else if (isReady) {\n onChoose(conn.id)\n }\n }\n\n return (\n <button\n key={conn.id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isSelected}\n className={css.row}\n disabled={isReady ? state.saving : !canOpenSettings}\n title={text.reason ?? text.label}\n onClick={onClick}\n >\n <div className={css.rowContent}>\n <span className={css.rowLabel}>{text.label}</span>\n {text.caption && !text.reason && (\n <span className={css.rowCaption}>{text.caption}</span>\n )}\n {text.reason && (\n <span className={clsx(css.rowCaption, css.rowCaptionWarn)}>\n <span className={css.warnDot} aria-hidden=\"true\" />\n <span>{text.reason}</span>\n </span>\n )}\n </div>\n <span className={css.check}>\n {isSelected && <IconCheckOutlineRegular size={14} />}\n </span>\n </button>\n )\n })}\n </div>\n\n {view.connections.length === 0 && <div className={css.empty}>{t('menu.empty')}</div>}\n\n {section.Options && (\n <div className={css.optionsWrapper}>\n <section.Options sessionId={sessionId} />\n </div>\n )}\n </>\n )}\n </div>\n </div>\n )\n}\n","export const NS = 'tool-web-enhanced-ui' as const\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'button.title': '网页连接',\n 'button.aria': '选择网页连接',\n 'button.loading': '正在加载…',\n 'button.readFailed': '读取失败',\n 'button.missing': '连接已移除',\n 'button.off': '已关闭',\n 'button.invalidSettings': '设置无效',\n 'button.side': '{capability}:{state}',\n 'button.sideAttention': '{capability}:{state}(需要处理)',\n 'menu.aria': '网页连接菜单',\n 'menu.tabs': '网页能力',\n 'menu.offRow': '关闭',\n 'menu.empty': '没有可用的连接',\n 'menu.settings': '设置',\n 'menu.routeWarning': '当前由 {provider} 提供,这里的选择不会生效。',\n 'menu.invalidSettings': '{capability}的设置无效,请打开设置修复。',\n \"disabled.search\": \"网页搜索暂不可用:增强网页搜索已停用,请在上方启用。\",\n \"disabled.fetch\": \"网页获取暂不可用:增强网页获取已停用,请在上方启用。\",\n 'disabled.openPlugins': '打开插件页',\n 'activation.title': '增强网页工具已启用',\n \"activation.body\": \"网页搜索和网页获取现在由本组合包的插件提供。点输入框右侧的地球按钮为每个会话选择连接;连接、密钥和默认值在插件设置里配置。\",\n 'activation.preflight': '之前的设置可能让本组合包无法接管网页工具。请打开设置查看详情,并按提示移除遗留设置。',\n 'activation.later': '稍后',\n 'activation.open': '打开设置',\n 'activation.close': '关闭',\n 'overview.title': '网页工具状态',\n \"overview.description\": \"网页搜索与网页获取由谁提供,以及从 0.1.x 升级后遗留的设置。\",\n 'overview.search.title': '网页搜索',\n 'overview.fetch.title': '网页获取',\n 'overview.status.routed': '由增强网页搜索提供',\n 'overview.status.routedFetch': '由增强网页获取提供',\n 'overview.status.notRouted': '未由增强网页搜索提供',\n 'overview.status.notRoutedFetch': '未由增强网页获取提供',\n 'overview.status.rowDisabled': '已关闭',\n 'overview.status.effective': '当前生效:{provider}',\n 'overview.status.base': '组合包默认:{provider}',\n 'overview.status.user': '你的设置:{provider}',\n 'overview.status.none': '未设置',\n 'preflight.title': '升级检查',\n 'preflight.healthy': '没有发现遗留设置。',\n 'preflight.userOverride': '你的设置把 {tool} 交给了 {value},不再经过本组合包。',\n 'preflight.legacyRemnant': '{tool} 仍指向 0.1.x 留下的、已不存在的 provider,{action}会失败。',\n 'preflight.action.searchAction': '搜索',\n 'preflight.action.fetchAction': '获取网页',\n 'preflight.nativeSearchConflict': '内置的 DeepSeek 网页搜索插件已重新开启,可能接管网页搜索。不需要时请关闭它。',\n 'preflight.action.fix': '移除遗留设置',\n 'preflight.confirm.title': '移除遗留设置',\n 'preflight.confirm.body': '将从你的设置中移除 {fields},恢复本组合包 的选择。',\n 'preflight.confirm.confirm': '移除',\n 'preflight.confirm.cancel': '取消',\n 'preflight.confirm.close': '关闭',\n 'preflight.action.success': '已移除设置',\n 'preflight.action.failed': '未修改:设置可能已在别处更改,请重试。',\n} satisfies Record<string, string>\n\nexport type LocaleKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'button.title': 'Web connections',\n 'button.aria': 'Choose web connections',\n 'button.loading': 'Loading…',\n 'button.readFailed': \"Couldn't load\",\n 'button.missing': 'Connection removed',\n 'button.off': 'Off',\n 'button.invalidSettings': 'Invalid settings',\n 'button.side': '{capability}: {state}',\n 'button.sideAttention': '{capability}: {state} (needs attention)',\n 'menu.aria': 'Web connections menu',\n 'menu.tabs': 'Web capabilities',\n 'menu.offRow': 'Off',\n 'menu.empty': 'No connections available',\n 'menu.settings': 'Settings',\n 'menu.routeWarning': 'Served by {provider}; choices here have no effect.',\n 'menu.invalidSettings': '{capability} settings are invalid. Open settings to fix them.',\n \"disabled.search\": \"Web search isn't available because Web Search Enhanced is off. Turn it on above.\",\n \"disabled.fetch\": \"Web fetch isn't available because Web Fetch Enhanced is off. Turn it on above.\",\n 'disabled.openPlugins': 'Open Plugins page',\n 'activation.title': 'Web Tools Enhanced is enabled',\n \"activation.body\": \"Web search and web fetch now go through this bundle's plugins. Pick a connection for each conversation with the globe button in the composer; set up connections, keys and defaults in the plugin settings.\",\n 'activation.preflight': 'Some previous settings may stop this bundle from handling web tools. Open settings to review them and remove leftover settings.',\n 'activation.later': 'Later',\n 'activation.open': 'Open settings',\n 'activation.close': 'Close',\n 'overview.title': 'Web tools status',\n \"overview.description\": \"Which service handles web search and web fetch, and settings left over from 0.1.x.\",\n 'overview.search.title': 'Web search',\n 'overview.fetch.title': 'Web fetch',\n 'overview.status.routed': 'Served by Web Search Enhanced',\n 'overview.status.routedFetch': 'Served by Web Fetch Enhanced',\n 'overview.status.notRouted': 'Not served by Web Search Enhanced',\n 'overview.status.notRoutedFetch': 'Not served by Web Fetch Enhanced',\n 'overview.status.rowDisabled': 'Off',\n 'overview.status.effective': 'Effective: {provider}',\n 'overview.status.base': 'Bundle default: {provider}',\n 'overview.status.user': 'Your setting: {provider}',\n 'overview.status.none': 'Not set',\n 'preflight.title': 'Upgrade check',\n 'preflight.healthy': 'No leftover settings found.',\n 'preflight.userOverride': 'Your settings route {tool} to {value}, so it bypasses this bundle.',\n 'preflight.legacyRemnant': '{tool} is set to a provider from 0.1.x that no longer exists, so {action} fail.',\n 'preflight.action.searchAction': 'searches',\n 'preflight.action.fetchAction': 'fetches',\n 'preflight.nativeSearchConflict': 'The built-in DeepSeek web search plugin is on again and can take over web search. Turn it off unless you need it.',\n 'preflight.action.fix': 'Remove leftover settings',\n 'preflight.confirm.title': 'Remove leftover settings',\n 'preflight.confirm.body': \"This removes {fields} from your settings and restores this bundle's choice.\",\n 'preflight.confirm.confirm': 'Remove',\n 'preflight.confirm.cancel': 'Cancel',\n 'preflight.confirm.close': 'Close',\n 'preflight.action.success': 'Settings removed',\n 'preflight.action.failed': 'Not changed. The settings may have changed elsewhere; try again.',\n} satisfies Record<LocaleKey, string>\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'tool-web-enhanced-ui': LocaleKey\n }\n}\n","import { useState } from 'react'\nimport {\n Button,\n IconCheckOutlineRegular,\n IconWarningOutlineRegular,\n Modal,\n StateDot,\n Toast,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PluginDetailProps, PluginsSubject } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type { ConfigForm, ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { PropsLocale, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport { FETCH, PROFILE_PACKAGE, SEARCH, WEB_FIELD, isRouted, type Route } from 'dsh-tool-web-enhanced-core/shared'\nimport { useObservable, type CapabilityName, type WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport { isCapabilityRowDisabled, routeFor } from './disabled.ts'\nimport type { NS } from './locales.ts'\nimport { buildUnsetOps, checkUpgradePreflight } from './preflight.ts'\nimport css from './ProfileDetailSection.module.css'\n\nexport type Translate = TranslateNS<typeof NS>\n\nexport interface ProfileDetailSectionProps extends PluginDetailProps, PropsLocale<typeof NS> {\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n readonly webConnections: WebConnectionsService\n}\n\nexport function ProfileDetailSection({\n subject,\n webConfigForm,\n nativeSearchServed,\n webConnections,\n t,\n}: ProfileDetailSectionProps) {\n if (subject.kind !== 'bundle' || subject.pkg.name !== PROFILE_PACKAGE) {\n return null\n }\n\n return (\n <ProfileDetailSectionInner\n subject={subject}\n webConfigForm={webConfigForm}\n nativeSearchServed={nativeSearchServed}\n webConnections={webConnections}\n t={t}\n />\n )\n}\n\nfunction ProfileDetailSectionInner({\n subject,\n webConfigForm,\n nativeSearchServed,\n webConnections,\n t,\n}: {\n readonly subject: Extract<PluginsSubject, { kind: 'bundle' }>\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n readonly webConnections: WebConnectionsService\n readonly t: Translate\n}) {\n const [confirmOpen, setConfirmOpen] = useState(false)\n const [mutating, setMutating] = useState(false)\n const [toast, setToast] = useState<{ text: string; ok: boolean } | null>(null)\n\n const webSnapshot = useObservable(webConfigForm)\n const routes = useObservable(webConnections.routes)\n\n const preflight = checkUpgradePreflight({\n user: webSnapshot.user,\n nativeSearchServed,\n })\n\n const healthy = preflight.issues.length === 0\n const canFix = preflight.fieldsToUnset.length > 0\n const lastFixableIssue = preflight.issues.findLast(issue => issue.kind !== 'native-search-conflict')\n\n const onConfirmReset = async (): Promise<void> => {\n if (preflight.fieldsToUnset.length === 0) return\n setMutating(true)\n try {\n const ops = buildUnsetOps(preflight.fieldsToUnset)\n const ok = await webConfigForm.mutate(ops, webSnapshot.revision)\n setToast({\n text: t(ok ? 'preflight.action.success' : 'preflight.action.failed'),\n ok,\n })\n } finally {\n setMutating(false)\n setConfirmOpen(false)\n }\n }\n\n return (\n <section className={css.section} aria-label={t('overview.title')}>\n <div className={css.header}>\n <h3 className={css.title}>{t('overview.title')}</h3>\n <p className={css.description}>{t('overview.description')}</p>\n </div>\n\n <div className={css.container}>\n <CapabilityCard\n title={t('overview.search.title')}\n capability=\"search\"\n providerId={SEARCH.providerId}\n rowDisabled={isCapabilityRowDisabled({ rowId: SEARCH.rowId, rows: subject.pkg.rows })}\n webSnapshot={webSnapshot}\n routes={routes}\n t={t}\n />\n <CapabilityCard\n title={t('overview.fetch.title')}\n capability=\"fetch\"\n providerId={FETCH.providerId}\n rowDisabled={isCapabilityRowDisabled({ rowId: FETCH.rowId, rows: subject.pkg.rows })}\n webSnapshot={webSnapshot}\n routes={routes}\n t={t}\n />\n\n {/* Upgrade Preflight Row */}\n <div className={css.preflightBox}>\n <div className={css.preflightHeader}>\n <span className={css.preflightTitle}>{t('preflight.title')}</span>\n </div>\n\n {healthy ? (\n <div className={css.healthyText}>{t('preflight.healthy')}</div>\n ) : (\n <div className={css.issuesList}>\n {preflight.issues.map((issue, idx) => (\n <div key={idx} className={css.issueItem}>\n <IconWarningOutlineRegular className={css.issueIcon} size={16} />\n <div>\n <span>\n {issue.kind === 'user-override' &&\n t('preflight.userOverride', {\n tool: t(issue.field === 'searchProvider' ? 'overview.search.title' : 'overview.fetch.title'),\n value: issue.value,\n })}\n {issue.kind === 'legacy-remnant' &&\n t('preflight.legacyRemnant', {\n tool: t(issue.field === 'searchProvider' ? 'overview.search.title' : 'overview.fetch.title'),\n action:\n issue.field === 'searchProvider'\n ? t('preflight.action.searchAction')\n : t('preflight.action.fetchAction'),\n })}\n {issue.kind === 'native-search-conflict' &&\n t('preflight.nativeSearchConflict')}\n </span>\n {canFix && issue === lastFixableIssue && (\n <div className={css.fixableActionRow}>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setConfirmOpen(true)}>\n {t('preflight.action.fix')}\n </Button>\n </div>\n )}\n </div>\n </div>\n ))}\n\n\n </div>\n )}\n </div>\n </div>\n\n {confirmOpen && (\n <Modal\n open\n title={t('preflight.confirm.title')}\n closeLabel={t('preflight.confirm.close')}\n onClose={() => setConfirmOpen(false)}\n footer={\n <>\n <Button variant=\"ghost\" onClick={() => setConfirmOpen(false)}>\n {t('preflight.confirm.cancel')}\n </Button>\n <Button\n variant=\"primary\"\n disabled={mutating}\n onClick={() => void onConfirmReset()}\n >\n {t('preflight.confirm.confirm')}\n </Button>\n </>\n }\n >\n <p>{t('preflight.confirm.body', { fields: preflight.fieldsToUnset.join(', ') })}</p>\n </Modal>\n )}\n\n {toast !== null && (\n <Toast\n text={toast.text}\n icon={toast.ok ? <IconCheckOutlineRegular /> : <IconWarningOutlineRegular />}\n holdMs={3000}\n onDone={() => setToast(null)}\n />\n )}\n </section>\n )\n}\n\nfunction RouteBadge({ capability, route, rowDisabled, t }: {\n readonly capability: 'search' | 'fetch'\n readonly route: Route\n readonly rowDisabled: boolean\n readonly t: Translate\n}) {\n const routed = isRouted(route)\n const routedKey = capability === 'search' ? 'overview.status.routed' : 'overview.status.routedFetch'\n const notRoutedKey = capability === 'search' ? 'overview.status.notRouted' : 'overview.status.notRoutedFetch'\n const key = rowDisabled ? 'overview.status.rowDisabled' : routed ? routedKey : notRoutedKey\n const healthy = routed && !rowDisabled\n return (\n <span className={healthy ? css.routedBadge : css.notRoutedBadge}>\n <StateDot state={healthy ? 'done' : 'warning'} />\n {t(key)}\n </span>\n )\n}\n\nfunction renderProviderLine(labelTemplate: string, provider: string, noneText: string) {\n const parts = labelTemplate.split('{provider}')\n if (parts.length === 1) return <span>{labelTemplate}</span>\n return (\n <span>\n {parts[0]}\n {provider === noneText ? provider : <code>{provider}</code>}\n {parts[1]}\n </span>\n )\n}\n\nfunction CapabilityCard({\n title,\n capability,\n providerId,\n rowDisabled,\n webSnapshot,\n routes,\n t,\n}: {\n readonly title: string\n readonly capability: CapabilityName\n readonly providerId: string\n readonly rowDisabled: boolean\n readonly webSnapshot: ConfigFormSnapshot<Record<string, unknown>>\n readonly routes: ReadonlyMap<CapabilityName, Route>\n readonly t: Translate\n}) {\n const field = WEB_FIELD[capability]\n const webBase = (typeof webSnapshot.base === 'object' && webSnapshot.base !== null ? webSnapshot.base : {}) as Record<string, unknown>\n const webUser = (typeof webSnapshot.user === 'object' && webSnapshot.user !== null ? webSnapshot.user : {}) as Record<string, unknown>\n const currentRoute = routeFor(capability, routes, webSnapshot.value)\n\n const noneText = t('overview.status.none')\n\n const effectiveProvider = currentRoute.kind === 'this' ? providerId : currentRoute.kind === 'other' ? currentRoute.provider : noneText\n const baseProvider = typeof webBase[field] === 'string' ? webBase[field] : noneText\n const userProvider = typeof webUser[field] === 'string' ? webUser[field] : noneText\n\n return (\n <div className={css.card}>\n <div className={css.cardHeader}>\n <span className={css.cardTitle}>{title}</span>\n <RouteBadge\n capability={capability}\n route={currentRoute}\n rowDisabled={rowDisabled}\n t={t}\n />\n </div>\n\n <div className={css.statusList}>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.effective'), effectiveProvider, noneText)}\n </div>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.base'), baseProvider, noneText)}\n </div>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.user'), userProvider, noneText)}\n </div>\n </div>\n\n {rowDisabled && (\n <div className={css.warnBox}>\n <IconWarningOutlineRegular size={14} className={css.warnIcon} />\n <span>{t(field === 'searchProvider' ? 'disabled.search' : 'disabled.fetch')}</span>\n </div>\n )}\n </div>\n )\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport type { CapabilityName, ConnectionSection, RouteStore, WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport type { Route } from 'dsh-tool-web-enhanced-core/shared'\n\nexport { createSnapshotStore }\n\n/**\n * Pure factory for the WebConnectionsService interface.\n */\nexport function createWebConnectionsService(): WebConnectionsService {\n const store = createSnapshotStore<readonly ConnectionSection[]>([])\n const registered = new Set<ConnectionSection>()\n const routes = createSnapshotStore<ReadonlyMap<CapabilityName, Route>>(new Map())\n const routeSources = new Set<{ readonly capability: CapabilityName; readonly route: RouteStore }>()\n\n const publishRoutes = (): void => {\n const next = new Map<CapabilityName, Route>()\n for (const entry of routeSources) next.set(entry.capability, entry.route.source.getSnapshot())\n routes.set(next)\n }\n\n const publish = (): void => {\n const sorted = [...registered].toSorted((a, b) => a.order - b.order)\n store.set(sorted)\n }\n\n return {\n routes,\n registerRoute(capability, route) {\n const entry = { capability, route }\n routeSources.add(entry)\n const unsubscribe = route.source.subscribe(publishRoutes)\n publishRoutes()\n return () => {\n if (!routeSources.delete(entry)) return\n unsubscribe()\n publishRoutes()\n }\n },\n get sections(): ObservableSnapshot<readonly ConnectionSection[]> {\n return store\n },\n register(section: ConnectionSection): () => void {\n registered.add(section)\n publish()\n return () => {\n if (registered.delete(section)) {\n publish()\n }\n }\n },\n }\n}\n\n/**\n * Installs the webConnections service on a Cordis Context.\n */\nexport function installWebConnectionsService(ctx: Context): WebConnectionsService {\n const service = createWebConnectionsService()\n ctx.provide('webConnections', service)\n return service\n}\n","/**\n * Browser face of dsh-tool-web-enhanced-ui:\n * - webConnections browser service (registry for connection sections)\n * - conversation.input.right: single web connection button and dropdown menu\n * - plugins.bundle.activation: activation guidance modal for the profile bundle\n * - plugins.detail.section: profile bundle overview and upgrade preflight\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { PluginActivationOwnerProps, PluginDetailProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { FETCH, PROFILE_PACKAGE, SEARCH, UI } from 'dsh-tool-web-enhanced-core/shared'\nimport { useObservable } from 'dsh-tool-web-enhanced-core/client'\nimport { ActivationPrompt } from './ActivationPrompt.tsx'\nimport { ComposerConnectionMenu, modelKeyOf } from './ComposerConnectionMenu.tsx'\nimport { en, NS, zh } from './locales.ts'\nimport { NATIVE_SEARCH_ROW } from './preflight.ts'\nimport { ProfileDetailSection } from './ProfileDetailSection.tsx'\nimport { createSnapshotStore, installWebConnectionsService } from './service.ts'\n\nexport const inject = ['slots', 'locale', 'configForms']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'tool-web-enhanced-ui: dictionaries')\n\n const webConnections = installWebConnectionsService(ctx)\n const webConfigForm = ctx.configForms.get<Record<string, unknown>>('web')\n\n let searchServed = false\n let fetchServed = false\n let nativeSearchServed = false\n\n const servedStore = createSnapshotStore({\n searchServed: false,\n fetchServed: false,\n nativeSearchServed: false,\n })\n\n const syncServed = (): void => {\n servedStore.set({ searchServed, fetchServed, nativeSearchServed })\n }\n\n // Check whileServed for search and fetch\n ctx.effect(\n () =>\n ctx.configForms.whileServed([SEARCH.rowId], () => {\n searchServed = true\n syncServed()\n return () => {\n searchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed search',\n )\n\n ctx.effect(\n () =>\n ctx.configForms.whileServed([FETCH.rowId], () => {\n fetchServed = true\n syncServed()\n return () => {\n fetchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed fetch',\n )\n\n ctx.effect(\n () =>\n ctx.configForms.whileServed([NATIVE_SEARCH_ROW], () => {\n nativeSearchServed = true\n syncServed()\n return () => {\n nativeSearchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed native search',\n )\n\n // The store holds an object, never the bare callback: `set(fn)` would run `fn` as an updater.\n const openPluginsStore = createSnapshotStore<{ readonly open: (() => void) | undefined }>({ open: undefined })\n ctx.inject(['pluginNavigation'], scope => {\n scope.effect(() => {\n openPluginsStore.set({ open: () => { scope.pluginNavigation.openBundle(PROFILE_PACKAGE) } })\n return () => {\n openPluginsStore.set({ open: undefined })\n }\n }, 'tool-web-enhanced-ui: pluginNavigation')\n })\n\n // 1. Composer connection button & menu\n function ComposerButtonSlot(\n props: PropsRuntime<'conversation.input.right'> & PropsLocale<typeof NS>,\n ) {\n const served = useObservable(servedStore)\n const webSnapshot = useObservable(webConfigForm)\n const onOpenPlugins = useObservable(openPluginsStore).open\n const modelKey = props.useProjection('modelSelection', modelKeyOf as (val: unknown) => unknown) as string\n\n return (\n <ComposerConnectionMenu\n sessionId={props.sessionId}\n modelKey={modelKey}\n webConnections={webConnections}\n searchServed={served.searchServed}\n fetchServed={served.fetchServed}\n webConfig={webSnapshot.value}\n onOpenPlugins={onOpenPlugins}\n t={props.t}\n />\n )\n }\n\n ctx.slots.inject('conversation.input.right', () =>\n ctx.slots.register(\n {\n name: 'conversation.input.right',\n id: UI.rowId,\n order: 20,\n locale: NS,\n },\n ComposerButtonSlot,\n ),\n )\n\n // 2. Activation prompt\n function ActivationSlot(props: PluginActivationOwnerProps & PropsLocale<typeof NS>) {\n const served = useObservable(servedStore)\n return <ActivationPrompt {...props} webConfigForm={webConfigForm} nativeSearchServed={served.nativeSearchServed} />\n }\n ctx.slots.inject('plugins.bundle.activation', () =>\n ctx.slots.register(\n {\n name: 'plugins.bundle.activation',\n key: PROFILE_PACKAGE,\n locale: NS,\n },\n ActivationSlot,\n ),\n )\n\n // 3. Profile detail overview section\n function DetailSectionSlot(props: PluginDetailProps & PropsLocale<typeof NS>) {\n const served = useObservable(servedStore)\n\n return (\n <ProfileDetailSection\n subject={props.subject}\n webConfigForm={webConfigForm}\n nativeSearchServed={served.nativeSearchServed}\n webConnections={webConnections}\n t={props.t}\n />\n )\n }\n\n ctx.slots.inject('plugins.detail.section', () =>\n ctx.slots.register(\n {\n name: 'plugins.detail.section',\n id: 'tool-web-enhanced-ui-overview',\n locale: NS,\n },\n DetailSectionSlot,\n ),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAQA,MAAa,kBAAkB;EAgB/B,MAAa,SAAyB;GACpC,aAAa;GACb,OAAO;GACP,YAAY;EACd;EAEA,MAAa,QAAwB;GACnC,aAAa;GACb,OAAO;GACP,YAAY;EACd;;EAGA,MAAa,KAAkB;GAC7B,aAAa;GACb,OAAO;EACT;;;ECpBA,MAAa,YAAY;GAAE,QAAQ;GAAkB,OAAO;EAAgB;;;;;;;EAS5E,SAAgB,QAAQ,KAAoD,OAAe,aAA4B,YAA2B;GAChJ,IAAI,QAAQ,KAAA,GAAW,OAAO,EAAE,MAAM,UAAU;GAChD,MAAM,aAAa,IAAI;GAEvB,MAAM,SAAS,OAAO,eAAe,WAAW,aAAa;GAC7D,IAAI,WAAW,MAAM,OAAO;IAAE,MAAM;IAAQ;GAAW;GACvD,OAAO,WAAW,aAAa,EAAE,MAAM,OAAO,IAAI;IAAE,MAAM;IAAS,UAAU;IAAQ;GAAW;EAClG;;EAGA,MAAa,YAAY,UAA0B,MAAM,SAAS;;;;;;;;;EC9BlE,SAAgB,cAAiB,QAAkC;GACjE,MAAM,aAAA,GAAYA,MAAAA,YAAAA,EAAa,aAAyB,OAAO,UAAU,QAAQ,GAAG,CAAC,MAAM,CAAC;GAC5F,MAAM,eAAA,GAAcA,MAAAA,YAAAA,OAAkB,OAAO,YAAY,GAAG,CAAC,MAAM,CAAC;GACpE,QAAA,GAAOC,MAAAA,qBAAAA,CAAqB,WAAW,WAAW;EACpD;;;ECVA,MAAa,0BAA6C,CACxD,qBACA,qBACF;EACA,MAAa,yBAA4C,CACvD,QACA,oBACF;EACA,MAAa,oBAAoB;;;;EA+BjC,SAAgB,sBAAsB,QAGX;GACzB,MAAM,SAA2B,CAAC;GAClC,MAAM,gBAAwD,CAAC;GAE/D,MAAM,OACJ,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,OAC9C,OAAO,OACR,KAAA;GAEN,IAAI,SAAS,KAAA,GAAW;IACtB,IAAI,oBAAoB,QAAQ,OAAO,KAAK,mBAAmB,UAAU;KACvE,MAAM,MAAM,KAAK;KACjB,IAAI,QAAQ,OAAO,YAAY;MAC7B,cAAc,KAAK,gBAAgB;MACnC,IAAI,wBAAwB,SAAS,GAAG,GACtC,OAAO,KAAK;OACV,MAAM;OACN,OAAO;OACP,OAAO;MACT,CAAC;WAED,OAAO,KAAK;OACV,MAAM;OACN,OAAO;OACP,OAAO;MACT,CAAC;KAEL;IACF;IAEA,IAAI,mBAAmB,QAAQ,OAAO,KAAK,kBAAkB,UAAU;KACrE,MAAM,MAAM,KAAK;KACjB,IAAI,QAAQ,MAAM,YAAY;MAC5B,cAAc,KAAK,eAAe;MAClC,IAAI,uBAAuB,SAAS,GAAG,GACrC,OAAO,KAAK;OACV,MAAM;OACN,OAAO;OACP,OAAO;MACT,CAAC;WAED,OAAO,KAAK;OACV,MAAM;OACN,OAAO;OACP,OAAO;MACT,CAAC;KAEL;IACF;GACF;GAEA,IAAI,OAAO,oBACT,OAAO,KAAK;IACV,MAAM;IACN,OAAO;GACT,CAAC;GAGH,OAAO;IACL;IACA;GACF;EACF;;;;EAKA,SAAgB,cACd,QACsB;GACtB,OAAO,OAAO,KAAI,WAAU;IAC1B,IAAI;IACJ,MAAM,CAAC,KAAK;GACd,EAAE;EACJ;;;EC1GA,SAAgB,iBAAiB,EAAE,WAAW,eAAe,eAAe,oBAAoB,KAA4B;GAG1H,MAAM,YADY,sBAAsB;IAAE,MAD9B,cAAc,aACsB,CAAA,CAAI;IAAM;GAAmB,CACnD,CAAC,CAAC,OAAO,SAAS;GAC5C,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;IACE,MAAA;IACA,OAAO,EAAE,kBAAkB;IAC3B,YAAY,EAAE,kBAAkB;IAChC,SAAS;IACT,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,QAAD;KAAQ,SAAQ;KAAQ,SAAS;KAC9B,UAAA,EAAE,kBAAkB;IACf,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;KAAQ,SAAQ;KAAU,wBAAA;KAAqB,SAAS;KACrD,UAAA,EAAE,iBAAiB;IACd,CAAA,CACR,EAAA,CAAA;IAGJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD,EAAA,UAAI,EAAE,YAAY,yBAAyB,iBAAiB,EAAK,CAAA;GAC5D,CAAA;EAEX;;;ECrBA,MAAM,cAAc;GAAE,QAAQ,OAAO;GAAY,OAAO,MAAM;EAAW;;;;;EAMzE,SAAgB,SAAS,YAA4B,QAA4C,WAAiD;GAChJ,MAAM,aAAa,OAAO,IAAI,UAAU;GACxC,OAAO,eAAe,KAAA,IAAY,QAAQ,WAAW,UAAU,aAAa,MAAM,YAAY,WAAW,IAAI;EAC/G;;;;;EAMA,SAAgB,0BAA0B,QAKX;GAC7B,MAAM,iBAAiB,SAAS,UAAU,OAAO,QAAQ,OAAO,SAAS,CAAC,CAAC,SAAS,UAAU,CAAC,OAAO;GACtG,MAAM,gBAAgB,SAAS,SAAS,OAAO,QAAQ,OAAO,SAAS,CAAC,CAAC,SAAS,UAAU,CAAC,OAAO;GAIpG,OAAO;IACL;IACA;IACA,aALkB,kBAAkB;GAMtC;EACF;;;;EAKA,SAAgB,wBAAwB,QAG5B;GACV,MAAM,MAAM,OAAO,KAAK,MAAK,MAAK,EAAE,UAAU,OAAO,KAAK;GAC1D,OAAO,QAAQ,KAAA,KAAa,CAAC,IAAI;EACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC3BA,SAAS,KAAK,GAAG,SAA0D;GACzE,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACzC;EAaA,SAAS,UAAU,SAA4B,OAAkC;GAC/E,IAAI,MAAM,gBAAgB,oBAAoB,OAAO,EAAE,MAAM,mBAAmB;GAChF,IAAI,MAAM,gBAAgB,UAAU,OAAO,EAAE,MAAM,cAAc;GACjE,MAAM,EAAE,SAAS;GACjB,IAAI,SAAS,KAAA,GAAW,OAAO,EAAE,MAAM,UAAU;GACjD,MAAM,EAAE,iBAAiB,KAAK;GAC9B,IAAI,iBAAiB,MAAM,OAAO,EAAE,MAAM,MAAM;GAChD,MAAM,WAAW,KAAK,YAAY,MAAK,eAAc,WAAW,OAAO,YAAY;GACnF,IAAI,aAAa,KAAA,GAAW,OAAO,EAAE,MAAM,UAAU;GACrD,OAAO;IAAE,MAAM;IAAc,OAAO,QAAQ,SAAS,QAAQ,CAAC,CAAC;IAAO,OAAO,SAAS,WAAW;GAAQ;EAC3G;EAEA,SAAS,SAAS,MAAiB,GAAsB;GACvD,QAAQ,KAAK,MAAb;IACE,KAAK,WAAW,OAAO,EAAE,gBAAgB;IACzC,KAAK,eAAe,OAAO,EAAE,mBAAmB;IAChD,KAAK,oBAAoB,OAAO,EAAE,wBAAwB;IAC1D,KAAK,OAAO,OAAO,EAAE,YAAY;IACjC,KAAK,WAAW,OAAO,EAAE,gBAAgB;IACzC,KAAK,cAAc,OAAO,KAAK;GACjC;EACF;;EAGA,SAAS,eAAe,MAAiB,OAAuB;GAC9D,IAAI,MAAM,SAAS,SAAS,OAAO;GACnC,QAAQ,KAAK,MAAb;IACE,KAAK;IACL,KAAK,OAAO,OAAO;IACnB,KAAK;IACL,KAAK;IACL,KAAK,WAAW,OAAO;IACvB,KAAK,cAAc,OAAO,CAAC,KAAK;GAClC;EACF;;EAGA,SAAS,iBAAoB,SAA6E;GACxG,IAAI,OAAqB,CAAC;GAC1B,OAAO;IACL,cAAc;KACZ,MAAM,OAAO,QAAQ,KAAI,WAAU,OAAO,YAAY,CAAC;KACvD,IAAI,KAAK,WAAW,KAAK,UAAU,KAAK,MAAM,OAAO,UAAU,UAAU,KAAK,MAAM,GAAG,OAAO;KAC9F,OAAO;IACT;IACA,UAAU,UAAU;KAClB,MAAM,eAAe,QAAQ,KAAI,WAAU,OAAO,UAAU,QAAQ,CAAC;KACrE,aAAa;MACX,KAAK,MAAM,eAAe,cAAc,YAAY;KACtD;IACF;GACF;EACF;EAMA,SAAgB,WAAW,YAA0D;GACnF,MAAM,QAAQ,YAAY;GAC1B,OAAO,QAAQ,GAAG,MAAM,SAAS,GAAG,MAAM,UAAU;EACtD;EAEA,SAAS,gBAAgB,EACvB,MACA,WACA,UACA,WAMyD;GACzD,MAAM,CAAC,aAAa,mBAAA,GAAkBC,MAAAA,SAAAA,CAAiE,IAAI;GAE3G,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,MAAM;IAEX,MAAM,cAAc;KAClB,MAAM,SAAS,UAAU;KACzB,IAAI,CAAC,QAAQ;KACb,MAAM,OAAO,OAAO,sBAAsB;KAC1C,MAAM,QAAQ,SAAS;KACvB,MAAM,gBAAgB,OAAO,eAAe;KAC5C,MAAM,SAAS,OAAO,gBAAgB;KAGtC,MAAM,WACJ,QAAQ,SAAS,QAAQ,6BAA6B,KACtD,SAAS,cAAc,6BAA6B,KACpD,SAAS,cAAc,MAAM;KAC/B,MAAM,WAAW,WAAW,SAAS,sBAAsB,CAAC,CAAC,OAAO;KACpE,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI,IAAI,QAAQ,GAAG,OAAO,aAAa,EAAE;KACvE,MAAM,WAAW,KAAK,IAAI,GAAG,OAAO,aAAa,UAAU,EAAE;KAC7D,MAAM,QAAQ,KAAK,IAAI,eAAe,QAAQ;KAE9C,IAAI,OAAO,KAAK,QAAQ;KAExB,IAAI,OAAO,WAAW,KAAK,OAAO,SAAS,OAAO,aAAa,IAC7D,OAAO,KAAK;KAEd,IAAI,QAAQ,GAAG;MACb,MAAM,UAAU,KAAK,IAAI,SAAS,OAAO,aAAa,QAAQ,EAAE;MAChE,OAAO,KAAK,IAAI,KAAK,IAAI,MAAM,OAAO,GAAG,OAAO;KAClD;KAGA,IAAI,MAAM,KAAK,MAAM,IAAI;KACzB,IAAI,MAAM,MAAM,KAAK,SAAS,IAAI,UAAU,OAAO,cAAc,IAC/D,MAAM,KAAK,SAAS;KAEtB,IAAI,SAAS,GACX,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,IAAI,IAAI,OAAO,cAAc,SAAS,EAAE,CAAC;KAGlF,eAAe;MAAE;MAAM;MAAK;KAAS,CAAC;IACxC;IAEA,MAAM;IACN,OAAO,iBAAiB,UAAU,OAAO,IAAI;IAC7C,OAAO,iBAAiB,UAAU,KAAK;IAEvC,IAAI,WAAkC;IACtC,IAAI,OAAO,mBAAmB,eAAe,SAAS,SAAS;KAC7D,WAAW,IAAI,eAAe,KAAK;KACnC,SAAS,QAAQ,SAAS,OAAO;IACnC;IAEA,aAAa;KACX,UAAU,WAAW;KACrB,OAAO,oBAAoB,UAAU,OAAO,IAAI;KAChD,OAAO,oBAAoB,UAAU,KAAK;IAC5C;GACF,GAAG;IAAC;IAAM;IAAW;IAAU;GAAO,CAAC;GAEvC,OAAO,OAAO,cAAc;EAC9B;EAaA,SAAgB,uBAAuB,EACrC,WACA,UACA,gBACA,cACA,aACA,WACA,eACA,KAC8B;GAC9B,MAAM,WAAW,cAAc,eAAe,QAAQ;GACtD,MAAM,SAAS,cAAc,eAAe,MAAM;GAElD,IAAI,SAAS,WAAW,GACtB,OAAO;GAGT,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,6BAAD;IACa;IACD;IACA;IACF;IACM;IACD;IACF;IACI;IACZ;GACJ,CAAA;EAEL;EAEA,SAAS,4BAA4B,EACnC,WACA,UACA,UACA,QACA,cACA,aACA,WACA,eACA,KAWC;GACD,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GAEtC,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAgC,IAAI;GACpE,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAA+C,IAAI;GAC/E,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAgC,IAAI;GAChE,MAAM,UAAA,GAASC,MAAAA,OAAAA,CAAO,CAAC;GAEvB,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAA8B,IAAI;GAClD,MAAM,cAAA,GAAaA,MAAAA,OAAAA,CAAiC,IAAI;GACxD,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAA8B,IAAI;GAClD,MAAM,MAAA,GAAKC,MAAAA,MAAAA,CAAM;GAEjB,MAAM,WAAW,gBAAgB;IAC/B;IACA,WAAW;IACX,UAAU;IACV;GACF,CAAC;GACD,CAAA,GAAA,sCAAA,2BAAA,CAA2B,SAAS,MAAM,SAAS,OAAO;GAG1D,MAAM,SAAS,aAAa;GAC5B,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,QAAQ;IACb,QAAQ,SAAS,cAA2B,wCAAoC,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;GAClH,GAAG,CAAC,MAAM,CAAC;GAEX,MAAM,kBAAA,GAAiBC,MAAAA,QAAAA,OAAc,SAAS,UAAU,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,QAAQ,CAAC;GAC/F,MAAM,SAAS,eAAA,GAAcA,MAAAA,QAAAA,OACrB,iBAAiB,eAAe,KAAI,YAAW,QAAQ,UAAU,OAAO,SAAS,CAAC,CAAC,GACzF,CAAC,gBAAgB,SAAS,CAC5B,CAAC;GAED,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,KAAK,MAAM,WAAW,UACpB,QAAa,UAAU,KAAK,WAAW,QAAQ;GAEnD,GAAG;IAAC;IAAU;IAAW;GAAQ,CAAC;GAElC,MAAM,cAAoB;IACxB,QAAQ,KAAK;IACb,WAAW,SAAS,MAAM;GAC5B;GAEA,MAAM,uBAA6B;IACjC,IAAI,MACF,MAAM;SACD;KACL,QAAQ,IAAI;KACZ,YAAY,eAAe,EAAE,CAAE,UAAU;KACzC,KAAK,MAAM,WAAW,UACpB,QAAa,UAAU,KAAK,WAAW,QAAQ;IAEnD;GACF;GAEA,MAAM,aAAa,UAA+C;IAChE,IAAI,CAAC,QAAQ,MAAM,YAAY,aAAa;IAC5C,IAAI,MAAM,QAAQ,UAAU;KAC1B,MAAM,eAAe;KACrB,MAAM;IACR;GACF;GAEA,MAAM,SAAS,OAAO,SAA4B,iBAA+C;IAE/F,IADoB,QAAQ,UAAU,OAAO,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,MACrD,UAAU,iBAAiB,cAAc;KACxD,MAAM;KACN;IACF;IAEA,MAAM,MAAM,MAAM,QAAQ,UAAU,IAAI,WAAW,EAAE,aAAa,CAAC;IACnE,IAAI,CAAC,IAAI,IACP,UAAU;KAAE,KAAK,OAAO;KAAW,MAAM,QAAQ,iBAAiB,IAAI,KAAK;IAAE,CAAC;SAE9E,MAAM;GAEV;GAGA,MAAM,QAAQ,eAAe,KAAK,SAAS,UAAU;IACnD,MAAM,OAAO,UAAU,SAAS,OAAO,MAAO;IAC9C,MAAM,QAAQ,SAAS,MAAM,CAAC;IAC9B,MAAM,aAAa,QAAQ,MAAM;IACjC,MAAM,YAAY,eAAe,MAAM,SAAS,QAAQ,YAAY,QAAQ,SAAS,CAAC;IACtF,OAAO;KACL;KACA,YAAY,QAAQ;KACpB,OAAO,KAAK,SAAS,eAAe,QAAQ,EAAE,eAAe;MAAE;MAAY;KAAM,CAAC;KAClF,MAAM,EAAE,YAAY,yBAAyB,eAAe;MAAE;MAAY;KAAM,CAAC;KACjF;IACF;GACF,CAAC;GACD,MAAM,cAAc,MAAM,KAAI,SAAQ,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK;GAC3D,MAAM,SAAS,OAAO,MAAK,UAAS,MAAM,MAAM;GAGhD,MAAM,SAAS,eAAe,MAAK,YAAW,QAAQ,eAAe,QAAQ,KAAK,eAAe;GACjG,MAAM,SAAS,eAAuC,GAAG,GAAG,OAAO;GACnE,MAAM,WAAW,eAAuC,GAAG,GAAG,SAAS;GACvE,MAAM,CAAC,UAAU,GAAG,aAAa,MAAM,KAAK,UAAwC;IAClF,OAAO,KAAK;IACZ,IAAI,MAAM,KAAK,UAAU;IACzB,SAAS,QAAQ,KAAK,UAAU;IAChC,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;KAAM,WAAWC,0CAAI;KAAU,OAAO,KAAK;KAA3C,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAWA,0CAAI;MAAW,UAAA,KAAK,QAAQ,MAAM;KAAQ,CAAA,GAC1D,KAAK,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD;MAAU,OAAM;MAAU,WAAWD,0CAAI;KAAU,CAAA,CAClE;;GAEV,EAAE;GAEF,MAAM,WAAW,0BAA0B;IACzC;IACA;IACA;IACA;GACF,CAAC;GACD,MAAM,cAAc,CAClB,GAAI,SAAS,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,IAAI,CAAC,GACxD,GAAI,SAAS,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC,CACxD;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,MAAK,OAAM;KACT,QAAQ,UAAU;KAClB,UAAU,EAAE;IACd;IACA,WAAWA,0CAAI;IACJ;IANb,UAAA;KAQE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;MACE,KAAK;MACL,MAAK;MACL,WAAWA,0CAAI;MACf,cAAY;MACZ,iBAAc;MACd,iBAAe;MACf,iBAAe,OAAO,GAAG,GAAG,SAAS,KAAA;MACrC,OAAO;MACP,SAAS;MATX,UAAA;OAWE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;QAAM,WAAWA,0CAAI;QAArB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACE,sCAAAA,yBAAD,EAAyB,MAAM,GAAK,CAAA,GAEpC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAWF,0CAAI;SAClB,UAAA,MAAM,KAAI,SAAQ,KAAK,aACtB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAA4B,WAAWA,0CAAI;UAAU,aAAW,KAAK;UACnE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD,EAAU,OAAM,UAAW,CAAA;SACvB,GAFK,KAAK,UAEV,CACP;QACG,CAAA,CACF;;OACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAWD,0CAAI;QACnB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAWA,0CAAI;SAClB,UAAA,MAAM,KAAK,MAAM,UAChB,iBAAA,GAAA,kBAAA,KAAA,CAACG,MAAAA,UAAD,EAAA,UAAA,CACG,QAAQ,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWH,0CAAI;UAAe,eAAY;UAAO,UAAA;SAAO,CAAA,GAC5E,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;UAAM,WAAWA,0CAAI;UAAM,mBAAiB,KAAK;UAAjD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;WAAM,WAAWA,0CAAI;WAAY,UAAA,KAAK;UAAY,CAAA,GACjD,KAAK,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD;WAAU,OAAM;WAAU,WAAWD,0CAAI;UAAW,CAAA,CACnE;SACE,CAAA,CAAA,EAAA,GANK,KAAK,UAMV,CACX;QACG,CAAA;OACF,CAAA;OACL,SACC,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD;QAAU,OAAM;QAAU,WAAWD,0CAAI;OAAO,CAAA,IAEhD,iBAAA,GAAA,kBAAA,IAAA,CAACI,sCAAAA,+BAAD;QACE,MAAM;QACN,WAAW,KAAKJ,0CAAI,SAAS,QAAQA,0CAAI,WAAW;OACrD,CAAA;MAEG;;KAEP,SAAA,GACCK,UAAAA,aAAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAACC,sCAAAA,aAAD;MACE,KAAK;MACL,IAAI,GAAG,GAAG;MACV,WAAWN,0CAAI;MACf,OAAO,YAAY;OAAE,YAAY;OAAU,MAAM;OAAG,KAAK;MAAE;MAC3D,MAAK;MACL,cAAY,EAAE,WAAW;MAN3B,UAAA;OASE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,0CAAI;QACjB,UAAA,eAAe,KAAI,YAClB,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAD;SAEW;SACT,OAAO,SAAS,QAAQ,YAAY,QAAQ,SAAS;SAC1C;SACX,QAAQ,YAAY;SACpB,OAAO,MAAM,QAAQ,UAAU;SAC/B,SAAS,QAAQ,QAAQ,UAAU;SACnC,WAAU,WAAU,KAAK,OAAO,SAAS,MAAM;SAC/C,aAAa;SACV;QACJ,GAVM,QAAQ,UAUd,CACF;OACE,CAAA;OAEJ,YAAY,SAAS,KACpB,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,0CAAI;QACjB,UAAA,YAAY,KAAI,SACf,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAgB,WAAWA,0CAAI;SAAgB,MAAK;SAApD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACO,sCAAAA,2BAAD;UAA2B,MAAM;UAAI,WAAWP,0CAAI;SAAa,CAAA,GACjE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAA,UAAM,KAAU,CAAA,GACf,kBAAkB,KAAA,KACjB,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UACE,MAAK;UACL,WAAWA,0CAAI;UACf,eAAe;WACb,MAAM;WACN,cAAc;UAChB;UAEC,UAAA,EAAE,sBAAsB;SACnB,CAAA,CAEP,EAAA,CAAA,CACF;QAjBK,GAAA,IAiBL,CACN;OACE,CAAA;OAIP,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,0CAAI;QAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACQ,sCAAAA,eAAD;SACE,OAAO,CAAC,UAAW,GAAG,SAAS;SAC/B,OAAO,OAAO;SACd,UAAU;SACV,OAAO,EAAE,WAAW;QACrB,CAAA;OACE,CAAA;MACM;KACb,CAAA,GAAA,SAAS,IACX;KAED,WAAW,QACV,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;MAEE,MAAM,OAAO;MACb,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACF,sCAAAA,2BAAD,CAA4B,CAAA;MAClC,QAAQ;MACR,QAAQ;MACR,cAAc,UAAU,IAAI;KAC7B,GANM,OAAO,GAMb;IAEA;;EAET;EAEA,SAAS,aAAa,EACpB,SACA,OACA,WACA,QACA,OACA,SACA,UACA,aACA,KAWC;GACD,MAAM,QAAQ,cAAc,QAAQ,UAAU,OAAO,SAAS,CAAC;GAC/D,MAAM,aAAa,cAAc,QAAQ,QAAQ;GACjD,MAAM,WAAA,GAAUV,MAAAA,OAAAA,CAA8B,IAAI;GAElD,MAAM,OAAO,MAAM;GACnB,MAAM,SAAS,SAAS,KAAA;GAGxB,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,UAAU,CAAC,QAAQ;IACxB,QAAQ,SAAS,cAAc,yBAAuB,CAAC,EAAE,eAAe,EAAE,OAAO,UAAU,CAAC;GAC9F,GAAG,CAAC,QAAQ,MAAM,CAAC;GAEnB,MAAM,UAAU,SAAS,UAAU,SAAS,KAAK,GAAG,CAAC;GAErD,MAAM,SAAS,SAAS,KAAA,KAAa,MAAM,gBAAgB,KAAA,IAAY,QAAQ,WAAW,IAAI,IAAI;GAClG,MAAM,YAAY,UAAU;GAE5B,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,MAAK;IACL,IAAI;IACJ,mBAAiB;IACjB,oBAAkB;IAElB,eAAa,SAAS,KAAA,IAAY;IAClC,WAAW,KAAKG,0CAAI,OAAO,CAAC,UAAUA,0CAAI,aAAa;IAPzD,UAAA,CASE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,0CAAI;KAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD;MAAG,IAAI;MAAW,WAAWA,0CAAI;MAAS,OAAO,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK;MAA7F,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAWA,0CAAI;OAAiB,UAAA;MAAc,CAAA,GACnD,UACC,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAWA,0CAAI;OAAkB,eAAY;OAAO,UAAA;MAAO,CAAA,GACjE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAWA,0CAAI;OAAgB,UAAA;MAAa,CAAA,CAClD,EAAA,CAAA,CAEH;KAEF,CAAA,GAAA,eAAe,KAAA,KACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MACE,MAAK;MACL,WAAWA,0CAAI;MACf,cAAY,EAAE,eAAe;MAC7B,OAAO,EAAE,eAAe;MACxB,eAAe;OACb,YAAY;OACZ,WAAW;MACb;MAEA,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACU,sCAAAA,4BAAD,EAA4B,MAAM,GAAK,CAAA;KACjC,CAAA,CAEP;IAEL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,KAAK;KAAS,WAAWV,0CAAI;KAAlC,UAAA,CACG,MAAM,SAAS,WACd,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,0CAAI;MAAa,MAAK;MAAtC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACO,sCAAAA,2BAAD;OAA2B,MAAM;OAAI,WAAWP,0CAAI;MAAa,CAAA,GACjE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,qBAAqB,EAAE,UAAU,MAAM,SAAS,CAAC,EAAQ,CAAA,CAC/D;KAGN,CAAA,GAAA,MAAM,gBAAgB,qBAErB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,0CAAI;MAAa,MAAK;MAAtC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACO,sCAAAA,2BAAD;OAA2B,MAAM;OAAI,WAAWP,0CAAI;MAAa,CAAA,GACjE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,wBAAwB,EAAE,YAAY,QAAQ,MAAM,EAAE,CAAC,EAAQ,CAAA,CACrE;KACH,CAAA,IAAA,SAAS,KAAA,IACX,MAAM,gBAAgB,WACpB,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MACE,MAAK;MACL,WAAWA,0CAAI;MACf,eAAe;OACb,QAAa,UAAU,KAAK,SAAS;MACvC;MAEA,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAW,KAAKA,0CAAI,UAAUA,0CAAI,cAAc;OACnD,UAAA,EAAE,mBAAmB;MAClB,CAAA;KACA,CAAA,IAER,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWA,0CAAI;MAAQ,UAAA,EAAE,gBAAgB;KAAO,CAAA,IAGvD,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;MACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,MAAK;OAAO,cAAY,QAAQ,MAAM;OAA3C,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;QACE,MAAK;QACL,MAAK;QACL,gBAAc,KAAK,UAAU,iBAAiB;QAC9C,WAAWA,0CAAI;QACf,UAAU,MAAM;QAChB,eAAe,SAAS,IAAI;QAN9B,UAAA,CAQE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAWA,0CAAI;SAAW,UAAA,EAAE,aAAa;QAAQ,CAAA,GACvD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAWA,0CAAI;SAClB,UAAA,KAAK,UAAU,iBAAiB,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAACW,sCAAAA,yBAAD,EAAyB,MAAM,GAAK,CAAA;QACzE,CAAA,CACA;OAEP,CAAA,GAAA,KAAK,YAAY,KAAI,SAAQ;QAC5B,MAAM,OAAO,QAAQ,SAAS,IAAI;QAClC,MAAM,aAAa,KAAK,OAAO,KAAK,UAAU;QAC9C,MAAM,UAAU,KAAK,WAAW;QAChC,MAAM,kBAAkB,CAAC,WAAW,eAAe,KAAA;QAEnD,MAAM,gBAAgB;SACpB,IAAI,iBAAiB;UACnB,YAAY;UACZ,WAAW;SACb,OAAO,IAAI,SACT,SAAS,KAAK,EAAE;QAEpB;QAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;SAEE,MAAK;SACL,MAAK;SACL,gBAAc;SACd,WAAWX,0CAAI;SACf,UAAU,UAAU,MAAM,SAAS,CAAC;SACpC,OAAO,KAAK,UAAU,KAAK;SAClB;SARX,UAAA,CAUE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAWA,0CAAI;UAApB,UAAA;WACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YAAM,WAAWA,0CAAI;YAAW,UAAA,KAAK;WAAY,CAAA;WAChD,KAAK,WAAW,CAAC,KAAK,UACrB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YAAM,WAAWA,0CAAI;YAAa,UAAA,KAAK;WAAc,CAAA;WAEtD,KAAK,UACJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;YAAM,WAAW,KAAKA,0CAAI,YAAYA,0CAAI,cAAc;YAAxD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAWA,0CAAI;aAAS,eAAY;YAAQ,CAAA,GAClD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,KAAK,OAAa,CAAA,CACrB;;UAEL;SACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,0CAAI;UAClB,UAAA,cAAc,iBAAA,GAAA,kBAAA,IAAA,CAACW,sCAAAA,yBAAD,EAAyB,MAAM,GAAK,CAAA;SAC/C,CAAA,CACA;QAxBD,GAAA,KAAK,EAwBJ;OAEZ,CAAC,CACE;;MAEJ,KAAK,YAAY,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAWX,0CAAI;OAAQ,UAAA,EAAE,YAAY;MAAO,CAAA;MAElF,QAAQ,WACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAWA,0CAAI;OAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAQ,SAAT,EAA4B,UAAY,CAAA;MACrC,CAAA;KAEP,EAAA,CAAA,CAED;IACF,CAAA,CAAA;;EAET;;;EC/qBA,MAAa,KAAK;;EAGlB,MAAa,KAAK;GAChB,gBAAgB;GAChB,eAAe;GACf,kBAAkB;GAClB,qBAAqB;GACrB,kBAAkB;GAClB,cAAc;GACd,0BAA0B;GAC1B,eAAe;GACf,wBAAwB;GACxB,aAAa;GACb,aAAa;GACb,eAAe;GACf,cAAc;GACd,iBAAiB;GACjB,qBAAqB;GACrB,wBAAwB;GACxB,mBAAmB;GACnB,kBAAkB;GAClB,wBAAwB;GACxB,oBAAoB;GACpB,mBAAmB;GACnB,wBAAwB;GACxB,oBAAoB;GACpB,mBAAmB;GACnB,oBAAoB;GACpB,kBAAkB;GAClB,wBAAwB;GACxB,yBAAyB;GACzB,wBAAwB;GACxB,0BAA0B;GAC1B,+BAA+B;GAC/B,6BAA6B;GAC7B,kCAAkC;GAClC,+BAA+B;GAC/B,6BAA6B;GAC7B,wBAAwB;GACxB,wBAAwB;GACxB,wBAAwB;GACxB,mBAAmB;GACnB,qBAAqB;GACrB,0BAA0B;GAC1B,2BAA2B;GAC3B,iCAAiC;GACjC,gCAAgC;GAChC,kCAAkC;GAClC,wBAAwB;GACxB,2BAA2B;GAC3B,0BAA0B;GAC1B,6BAA6B;GAC7B,4BAA4B;GAC5B,2BAA2B;GAC3B,4BAA4B;GAC5B,2BAA2B;EAC7B;;EAKA,MAAa,KAAK;GAChB,gBAAgB;GAChB,eAAe;GACf,kBAAkB;GAClB,qBAAqB;GACrB,kBAAkB;GAClB,cAAc;GACd,0BAA0B;GAC1B,eAAe;GACf,wBAAwB;GACxB,aAAa;GACb,aAAa;GACb,eAAe;GACf,cAAc;GACd,iBAAiB;GACjB,qBAAqB;GACrB,wBAAwB;GACxB,mBAAmB;GACnB,kBAAkB;GAClB,wBAAwB;GACxB,oBAAoB;GACpB,mBAAmB;GACnB,wBAAwB;GACxB,oBAAoB;GACpB,mBAAmB;GACnB,oBAAoB;GACpB,kBAAkB;GAClB,wBAAwB;GACxB,yBAAyB;GACzB,wBAAwB;GACxB,0BAA0B;GAC1B,+BAA+B;GAC/B,6BAA6B;GAC7B,kCAAkC;GAClC,+BAA+B;GAC/B,6BAA6B;GAC7B,wBAAwB;GACxB,wBAAwB;GACxB,wBAAwB;GACxB,mBAAmB;GACnB,qBAAqB;GACrB,0BAA0B;GAC1B,2BAA2B;GAC3B,iCAAiC;GACjC,gCAAgC;GAChC,kCAAkC;GAClC,wBAAwB;GACxB,2BAA2B;GAC3B,0BAA0B;GAC1B,6BAA6B;GAC7B,4BAA4B;GAC5B,2BAA2B;GAC3B,4BAA4B;GAC5B,2BAA2B;EAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECzFA,SAAgB,qBAAqB,EACnC,SACA,eACA,oBACA,gBACA,KAC4B;GAC5B,IAAI,QAAQ,SAAS,YAAY,QAAQ,IAAI,SAAA,iCAC3C,OAAO;GAGT,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,2BAAD;IACW;IACM;IACK;IACJ;IACb;GACJ,CAAA;EAEL;EAEA,SAAS,0BAA0B,EACjC,SACA,eACA,oBACA,gBACA,KAOC;GACD,MAAM,CAAC,aAAa,mBAAA,GAAkBY,MAAAA,SAAAA,CAAS,KAAK;GACpD,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,KAAK;GAC9C,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAA+C,IAAI;GAE7E,MAAM,cAAc,cAAc,aAAa;GAC/C,MAAM,SAAS,cAAc,eAAe,MAAM;GAElD,MAAM,YAAY,sBAAsB;IACtC,MAAM,YAAY;IAClB;GACF,CAAC;GAED,MAAM,UAAU,UAAU,OAAO,WAAW;GAC5C,MAAM,SAAS,UAAU,cAAc,SAAS;GAChD,MAAM,mBAAmB,UAAU,OAAO,UAAS,UAAS,MAAM,SAAS,wBAAwB;GAEnG,MAAM,iBAAiB,YAA2B;IAChD,IAAI,UAAU,cAAc,WAAW,GAAG;IAC1C,YAAY,IAAI;IAChB,IAAI;KACF,MAAM,MAAM,cAAc,UAAU,aAAa;KACjD,MAAM,KAAK,MAAM,cAAc,OAAO,KAAK,YAAY,QAAQ;KAC/D,SAAS;MACP,MAAM,EAAE,KAAK,6BAA6B,yBAAyB;MACnE;KACF,CAAC;IACH,UAAU;KACR,YAAY,KAAK;KACjB,eAAe,KAAK;IACtB;GACF;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;IAAS,WAAWC,wCAAI;IAAS,cAAY,EAAE,gBAAgB;IAA/D,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,wCAAI;MAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAAI,WAAWA,wCAAI;OAAQ,UAAA,EAAE,gBAAgB;MAAM,CAAA,GACnD,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAWA,wCAAI;OAAc,UAAA,EAAE,sBAAsB;MAAK,CAAA,CAC1D;;KAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,wCAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,gBAAD;QACE,OAAO,EAAE,uBAAuB;QAChC,YAAW;QACX,YAAY,OAAO;QACnB,aAAa,wBAAwB;SAAE,OAAO,OAAO;SAAO,MAAM,QAAQ,IAAI;QAAK,CAAC;QACvE;QACL;QACL;OACJ,CAAA;OACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,gBAAD;QACE,OAAO,EAAE,sBAAsB;QAC/B,YAAW;QACX,YAAY,MAAM;QAClB,aAAa,wBAAwB;SAAE,OAAO,MAAM;SAAO,MAAM,QAAQ,IAAI;QAAK,CAAC;QACtE;QACL;QACL;OACJ,CAAA;OAGD,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAWA,wCAAI;QAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAWA,wCAAI;SAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,wCAAI;UAAiB,UAAA,EAAE,iBAAiB;SAAQ,CAAA;QAC9D,CAAA,GAEJ,UACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAWA,wCAAI;SAAc,UAAA,EAAE,mBAAmB;QAAO,CAAA,IAE9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAWA,wCAAI;SACjB,UAAA,UAAU,OAAO,KAAK,OAAO,QAC5B,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAe,WAAWA,wCAAI;UAA9B,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,2BAAD;WAA2B,WAAWD,wCAAI;WAAW,MAAM;UAAK,CAAA,GAChE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD,EAAA,UAAA;WACG,MAAM,SAAS,mBACd,EAAE,0BAA0B;YAC1B,MAAM,EAAE,MAAM,UAAU,mBAAmB,0BAA0B,sBAAsB;YAC3F,OAAO,MAAM;WACf,CAAC;WACF,MAAM,SAAS,oBACd,EAAE,2BAA2B;YAC3B,MAAM,EAAE,MAAM,UAAU,mBAAmB,0BAA0B,sBAAsB;YAC3F,QACE,MAAM,UAAU,mBACZ,EAAE,+BAA+B,IACjC,EAAE,8BAA8B;WACxC,CAAC;WACF,MAAM,SAAS,4BACd,EAAE,gCAAgC;UAChC,EAAA,CAAA,GACL,UAAU,UAAU,oBACnB,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAWA,wCAAI;WAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACE,sCAAAA,QAAD;YAAQ,SAAQ;YAAU,MAAK;YAAK,eAAe,eAAe,IAAI;YACnE,UAAA,EAAE,sBAAsB;WACnB,CAAA;UACL,CAAA,CAEJ,EAAA,CAAA,CACF;SA5BK,GAAA,GA4BL,CACN;QAGE,CAAA,CAEJ;;MACF;;KAEJ,eACC,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;MACE,MAAA;MACA,OAAO,EAAE,yBAAyB;MAClC,YAAY,EAAE,yBAAyB;MACvC,eAAe,eAAe,KAAK;MACnC,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACD,sCAAAA,QAAD;OAAQ,SAAQ;OAAQ,eAAe,eAAe,KAAK;OACxD,UAAA,EAAE,0BAA0B;MACvB,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;OACE,SAAQ;OACR,UAAU;OACV,eAAe,KAAK,eAAe;OAElC,UAAA,EAAE,2BAA2B;MACxB,CAAA,CACR,EAAA,CAAA;MAGJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD,EAAA,UAAI,EAAE,0BAA0B,EAAE,QAAQ,UAAU,cAAc,KAAK,IAAI,EAAE,CAAC,EAAK,CAAA;KAC9E,CAAA;KAGR,UAAU,QACT,iBAAA,GAAA,kBAAA,IAAA,CAACE,sCAAAA,OAAD;MACE,MAAM,MAAM;MACZ,MAAM,MAAM,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,yBAAD,CAA0B,CAAA,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAACJ,sCAAAA,2BAAD,CAA4B,CAAA;MAC3E,QAAQ;MACR,cAAc,SAAS,IAAI;KAC5B,CAAA;IAEI;;EAEb;EAEA,SAAS,WAAW,EAAE,YAAY,OAAO,aAAa,KAKnD;GACD,MAAM,SAAS,SAAS,KAAK;GAG7B,MAAM,MAAM,cAAc,gCAAgC,SAFxC,eAAe,WAAW,2BAA2B,gCAClD,eAAe,WAAW,8BAA8B;GAE7E,MAAM,UAAU,UAAU,CAAC;GAC3B,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;IAAM,WAAW,UAAUD,wCAAI,cAAcA,wCAAI;IAAjD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACM,sCAAAA,UAAD,EAAU,OAAO,UAAU,SAAS,UAAY,CAAA,GAC/C,EAAE,GAAG,CACF;;EAEV;EAEA,SAAS,mBAAmB,eAAuB,UAAkB,UAAkB;GACrF,MAAM,QAAQ,cAAc,MAAM,YAAY;GAC9C,IAAI,MAAM,WAAW,GAAG,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,cAAoB,CAAA;GAC1D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD,EAAA,UAAA;IACG,MAAM;IACN,aAAa,WAAW,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,SAAe,CAAA;IACzD,MAAM;GACH,EAAA,CAAA;EAEV;EAEA,SAAS,eAAe,EACtB,OACA,YACA,YACA,aACA,aACA,QACA,KASC;GACD,MAAM,QAAQ,UAAU;GACxB,MAAM,UAAW,OAAO,YAAY,SAAS,YAAY,YAAY,SAAS,OAAO,YAAY,OAAO,CAAC;GACzG,MAAM,UAAW,OAAO,YAAY,SAAS,YAAY,YAAY,SAAS,OAAO,YAAY,OAAO,CAAC;GACzG,MAAM,eAAe,SAAS,YAAY,QAAQ,YAAY,KAAK;GAEnE,MAAM,WAAW,EAAE,sBAAsB;GAEzC,MAAM,oBAAoB,aAAa,SAAS,SAAS,aAAa,aAAa,SAAS,UAAU,aAAa,WAAW;GAC9H,MAAM,eAAe,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;GAC3E,MAAM,eAAe,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;GAE3E,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWN,wCAAI;IAApB,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,wCAAI;MAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAWA,wCAAI;OAAY,UAAA;MAAY,CAAA,GAC7C,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;OACc;OACZ,OAAO;OACM;OACV;MACJ,CAAA,CACE;;KAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,wCAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,wCAAI;QACjB,UAAA,mBAAmB,EAAE,2BAA2B,GAAG,mBAAmB,QAAQ;OAC5E,CAAA;OACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,wCAAI;QACjB,UAAA,mBAAmB,EAAE,sBAAsB,GAAG,cAAc,QAAQ;OAClE,CAAA;OACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAWA,wCAAI;QACjB,UAAA,mBAAmB,EAAE,sBAAsB,GAAG,cAAc,QAAQ;OAClE,CAAA;MACF;;KAEJ,eACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,wCAAI;MAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,2BAAD;OAA2B,MAAM;OAAI,WAAWD,wCAAI;MAAW,CAAA,GAC/D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,UAAU,mBAAmB,oBAAoB,gBAAgB,EAAQ,CAAA,CAC/E;;IAEJ;;EAET;;;;;;EC9RA,SAAgB,8BAAqD;GACnE,MAAM,SAAA,GAAQO,8BAAAA,oBAAAA,CAAkD,CAAC,CAAC;GAClE,MAAM,6BAAa,IAAI,IAAuB;GAC9C,MAAM,UAAA,GAASA,8BAAAA,oBAAAA,iBAAwD,IAAI,IAAI,CAAC;GAChF,MAAM,+BAAe,IAAI,IAAyE;GAElG,MAAM,sBAA4B;IAChC,MAAM,uBAAO,IAAI,IAA2B;IAC5C,KAAK,MAAM,SAAS,cAAc,KAAK,IAAI,MAAM,YAAY,MAAM,MAAM,OAAO,YAAY,CAAC;IAC7F,OAAO,IAAI,IAAI;GACjB;GAEA,MAAM,gBAAsB;IAC1B,MAAM,SAAS,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;IACnE,MAAM,IAAI,MAAM;GAClB;GAEA,OAAO;IACL;IACA,cAAc,YAAY,OAAO;KAC/B,MAAM,QAAQ;MAAE;MAAY;KAAM;KAClC,aAAa,IAAI,KAAK;KACtB,MAAM,cAAc,MAAM,OAAO,UAAU,aAAa;KACxD,cAAc;KACd,aAAa;MACX,IAAI,CAAC,aAAa,OAAO,KAAK,GAAG;MACjC,YAAY;MACZ,cAAc;KAChB;IACF;IACA,IAAI,WAA6D;KAC/D,OAAO;IACT;IACA,SAAS,SAAwC;KAC/C,WAAW,IAAI,OAAO;KACtB,QAAQ;KACR,aAAa;MACX,IAAI,WAAW,OAAO,OAAO,GAC3B,QAAQ;KAEZ;IACF;GACF;EACF;;;;EAKA,SAAgB,6BAA6B,KAAqC;GAChF,MAAM,UAAU,4BAA4B;GAC5C,IAAI,QAAQ,kBAAkB,OAAO;GACrC,OAAO;EACT;;;ECvCA,MAAa,SAAS;GAAC;GAAS;GAAU;EAAa;EAEvD,SAAgB,MAAM,KAAoB;GACxC,IAAI,aAAa,IAAI,OAAO,SAAS,IAAI;IAAE;IAAI;GAAG,CAAC,GAAG,oCAAoC;GAE1F,MAAM,iBAAiB,6BAA6B,GAAG;GACvD,MAAM,gBAAgB,IAAI,YAAY,IAA6B,KAAK;GAExE,IAAI,eAAe;GACnB,IAAI,cAAc;GAClB,IAAI,qBAAqB;GAEzB,MAAM,eAAA,GAAcC,8BAAAA,oBAAAA,CAAoB;IACtC,cAAc;IACd,aAAa;IACb,oBAAoB;GACtB,CAAC;GAED,MAAM,mBAAyB;IAC7B,YAAY,IAAI;KAAE;KAAc;KAAa;IAAmB,CAAC;GACnE;GAGA,IAAI,aAEA,IAAI,YAAY,YAAY,CAAC,OAAO,KAAK,SAAS;IAChD,eAAe;IACf,WAAW;IACX,aAAa;KACX,eAAe;KACf,WAAW;IACb;GACF,CAAC,GACH,0CACF;GAEA,IAAI,aAEA,IAAI,YAAY,YAAY,CAAC,MAAM,KAAK,SAAS;IAC/C,cAAc;IACd,WAAW;IACX,aAAa;KACX,cAAc;KACd,WAAW;IACb;GACF,CAAC,GACH,yCACF;GAEA,IAAI,aAEA,IAAI,YAAY,YAAY,CAAC,iBAAiB,SAAS;IACrD,qBAAqB;IACrB,WAAW;IACX,aAAa;KACX,qBAAqB;KACrB,WAAW;IACb;GACF,CAAC,GACH,iDACF;GAGA,MAAM,oBAAA,GAAmBA,8BAAAA,oBAAAA,CAAiE,EAAE,MAAM,KAAA,EAAU,CAAC;GAC7G,IAAI,OAAO,CAAC,kBAAkB,IAAG,UAAS;IACxC,MAAM,aAAa;KACjB,iBAAiB,IAAI,EAAE,YAAY;MAAE,MAAM,iBAAiB,WAAW,eAAe;KAAE,EAAE,CAAC;KAC3F,aAAa;MACX,iBAAiB,IAAI,EAAE,MAAM,KAAA,EAAU,CAAC;KAC1C;IACF,GAAG,wCAAwC;GAC7C,CAAC;GAGD,SAAS,mBACP,OACA;IACA,MAAM,SAAS,cAAc,WAAW;IACxC,MAAM,cAAc,cAAc,aAAa;IAC/C,MAAM,gBAAgB,cAAc,gBAAgB,CAAC,CAAC;IACtD,MAAM,WAAW,MAAM,cAAc,kBAAkB,UAAuC;IAE9F,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,wBAAD;KACE,WAAW,MAAM;KACP;KACM;KAChB,cAAc,OAAO;KACrB,aAAa,OAAO;KACpB,WAAW,YAAY;KACR;KACf,GAAG,MAAM;IACV,CAAA;GAEL;GAEA,IAAI,MAAM,OAAO,kCACf,IAAI,MAAM,SACR;IACE,MAAM;IACN,IAAI,GAAG;IACP,OAAO;IACP,QAAQ;GACV,GACA,kBACF,CACF;GAGA,SAAS,eAAe,OAA4D;IAClF,MAAM,SAAS,cAAc,WAAW;IACxC,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,kBAAD;KAAkB,GAAI;KAAsB;KAAe,oBAAoB,OAAO;IAAqB,CAAA;GACpH;GACA,IAAI,MAAM,OAAO,mCACf,IAAI,MAAM,SACR;IACE,MAAM;IACN,KAAK;IACL,QAAQ;GACV,GACA,cACF,CACF;GAGA,SAAS,kBAAkB,OAAmD;IAC5E,MAAM,SAAS,cAAc,WAAW;IAExC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,sBAAD;KACE,SAAS,MAAM;KACA;KACf,oBAAoB,OAAO;KACX;KAChB,GAAG,MAAM;IACV,CAAA;GAEL;GAEA,IAAI,MAAM,OAAO,gCACf,IAAI,MAAM,SACR;IACE,MAAM;IACN,IAAI;IACJ,QAAQ;GACV,GACA,iBACF,CACF;EACF"}
|
|
1
|
+
{"version":3,"file":"client.cjs","names":["useCallback","useSyncExternalStore","Modal","Button","useState","useRef","useId","useMemo","css","StateDot","IconGlobeOutlineRegular","Fragment","IconChevronDownOutlineRegular","createPortal","MenuSurface","IconWarningOutlineRegular","SegmentedTabs","Toast","IconSettingsOutlineRegular","IconCheckOutlineRegular","IconChevronRightOutlineRegular","useState","css","IconWarningOutlineRegular","Button","Modal","Toast","IconCheckOutlineRegular","StateDot","createSnapshotStore","createSnapshotStore"],"sources":["../../core/src/shared/ids.ts","../../core/src/shared/route.ts","../../core/src/client/use-observable.ts","../src/client/preflight.ts","../src/client/ActivationPrompt.tsx","../src/client/disabled.ts","../src/client/ComposerConnectionMenu.tsx","../src/client/locales.ts","../src/client/ProfileDetailSection.tsx","../src/client/service.ts","../src/client/index.tsx"],"sourcesContent":["/**\n * Identities that bind the profile bundle, its rows, and both faces together.\n * The profile's patch writes these ids, the plugins register them, and the\n * browser faces key their slots by them; tests assert all three agree.\n * Nothing here imports Node, the browser, or a Host package.\n */\n\n/** npm name of the profile bundle users install; the Plugins page keys bundle and row pages by it. */\nexport const PROFILE_PACKAGE = 'dsh-tool-web-enhanced-profile'\n\n/** A package the profile mounts as one row. */\nexport interface RowIdentity {\n /** npm package name; the profile bundle depends on it and names it in its row. */\n readonly packageName: string\n /** Row id the profile patch inserts; also the Settings namespace and the Cordis plugin name. */\n readonly rowId: string\n}\n\n/**\n * The two model-facing tools a capability registers while the operator has\n * them turned on and the `web` row routes the capability to this plugin.\n * Model-facing text calls a connection a \"provider\".\n */\nexport interface EnhancedToolNames {\n /** Runs one request on a provider the Agent names. */\n readonly action: string\n /** Lists the providers the Agent may name in this conversation. */\n readonly list: string\n}\n\n/** A row that serves one web capability. */\nexport interface PluginIdentity extends RowIdentity {\n /** Provider id registered in `ctx.web`; the profile writes it into the `web` row. */\n readonly providerId: string\n readonly tools: EnhancedToolNames\n}\n\nexport const SEARCH: PluginIdentity = {\n packageName: 'dsh-web-search-enhanced',\n rowId: 'web-search-enhanced',\n providerId: 'search-enhanced',\n tools: { action: 'web_search_enhanced', list: 'list_web_search_providers' },\n}\n\nexport const FETCH: PluginIdentity = {\n packageName: 'dsh-web-fetch-enhanced',\n rowId: 'web-fetch-enhanced',\n providerId: 'fetch-enhanced',\n tools: { action: 'web_fetch_enhanced', list: 'list_web_fetch_providers' },\n}\n\n/** The browser-only row holding the shared composer connection menu. */\nexport const UI: RowIdentity = {\n packageName: 'dsh-tool-web-enhanced-ui',\n rowId: 'tool-web-enhanced-ui',\n}\n\n/**\n * Key of a row's configuration page on the Plugins page (`plugins.row.config`).\n * @param row - the row the page configures.\n * @returns `<profile package>#<row id>`.\n */\nexport function rowConfigKey(row: RowIdentity): string {\n return `${PROFILE_PACKAGE}#${row.rowId}`\n}\n","/**\n * Whether the shared `web` row routes a capability to this plugin, judged the\n * way `WebRuntime` selects: the row's field, else the process environment\n * variable, else auto-selection. The Host reads the row through the public\n * Settings data; the browser reads it through `configForms.get('web')`. When\n * the row cannot be read, the answer is `unknown` and callers treat it as\n * \"not routed\".\n */\n\nexport type Route =\n /** The `web` row is not readable, or the Host has not answered yet. */\n | { readonly kind: 'unknown' }\n | { readonly kind: 'this' }\n /** Nothing pins a provider: `WebRuntime` auto-selects and fails while several are usable. */\n | { readonly kind: 'auto'; readonly providerId: string }\n /** Another provider serves the capability, so this plugin's settings have no effect. */\n | { readonly kind: 'other'; readonly provider: string; readonly providerId: string }\n\n/** The two `web` row fields and the environment variables `WebRuntime` reads instead. */\nexport const WEB_ROW = 'web'\nexport const WEB_FIELD = { search: 'searchProvider', fetch: 'fetchProvider' } as const\nexport const WEB_ENV = { search: 'DSH_WEB_SEARCH_PROVIDER', fetch: 'DSH_WEB_FETCH_PROVIDER' } as const\n\n/**\n * @param row - the `web` row's effective value, or undefined when it cannot be read.\n * @param field - which capability's field to judge.\n * @param envProvider - the process variable of that capability, or null when unset.\n * @param providerId - the id this plugin registered.\n */\nexport function routeOf(row: Readonly<Record<string, unknown>> | undefined, field: string, envProvider: string | null, providerId: string): Route {\n if (row === undefined) return { kind: 'unknown' }\n const configured = row[field]\n // Like `WebRuntime` (`config.searchProvider.get() ?? env`): only an absent field falls back to the variable.\n const pinned = typeof configured === 'string' ? configured : envProvider\n if (pinned === null) return { kind: 'auto', providerId }\n return pinned === providerId ? { kind: 'this' } : { kind: 'other', provider: pinned, providerId }\n}\n\n/** Whether the capability reaches this plugin; `unknown` and `auto` count as not routed. */\nexport const isRouted = (route: Route): boolean => route.kind === 'this'\n","import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport { useCallback, useSyncExternalStore } from 'react'\n\n/**\n * Read an observable snapshot in a component. The subscribe and getSnapshot\n * callbacks are stable per source, so React subscribes once per source rather\n * than once per render; a source that publishes on subscription would\n * otherwise re-render and re-subscribe without end.\n */\nexport function useObservable<T>(source: ObservableSnapshot<T>): T {\n const subscribe = useCallback((listener: () => void) => source.subscribe(listener), [source])\n const getSnapshot = useCallback(() => source.getSnapshot(), [source])\n return useSyncExternalStore(subscribe, getSnapshot)\n}\n","import { FETCH, SEARCH } from 'dsh-tool-web-enhanced-core/shared'\nimport type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client'\n\nexport const NATIVE_SEARCH_PROVIDERS: readonly string[] = [\n 'deepseek-official',\n 'deepseek-search-api',\n]\nexport const NATIVE_FETCH_PROVIDERS: readonly string[] = [\n 'http',\n 'deepseek-fetch-api',\n]\nexport const NATIVE_SEARCH_ROW = 'web-search-deepseek'\n\nexport type PreflightIssueKind =\n | 'user-override'\n | 'legacy-remnant'\n | 'native-search-conflict'\n\nexport type PreflightIssue =\n | {\n readonly kind: 'user-override'\n readonly field: 'searchProvider' | 'fetchProvider'\n readonly value: string\n }\n | {\n readonly kind: 'legacy-remnant'\n readonly field: 'searchProvider' | 'fetchProvider'\n readonly value: string\n }\n | {\n readonly kind: 'native-search-conflict'\n readonly rowId: string\n }\n\nexport interface UpgradePreflightResult {\n readonly issues: readonly PreflightIssue[]\n readonly fieldsToUnset: readonly ('searchProvider' | 'fetchProvider')[]\n}\n\n/**\n * Pure function to inspect settings and determine upgrade preflight issues (§11).\n */\nexport function checkUpgradePreflight(params: {\n readonly user?: unknown\n readonly nativeSearchServed: boolean\n}): UpgradePreflightResult {\n const issues: PreflightIssue[] = []\n const fieldsToUnset: ('searchProvider' | 'fetchProvider')[] = []\n\n const user =\n typeof params.user === 'object' && params.user !== null\n ? (params.user as Record<string, unknown>)\n : undefined\n\n if (user !== undefined) {\n if ('searchProvider' in user && typeof user.searchProvider === 'string') {\n const val = user.searchProvider\n if (val !== SEARCH.providerId) {\n fieldsToUnset.push('searchProvider')\n if (NATIVE_SEARCH_PROVIDERS.includes(val)) {\n issues.push({\n kind: 'user-override',\n field: 'searchProvider',\n value: val,\n })\n } else {\n issues.push({\n kind: 'legacy-remnant',\n field: 'searchProvider',\n value: val,\n })\n }\n }\n }\n\n if ('fetchProvider' in user && typeof user.fetchProvider === 'string') {\n const val = user.fetchProvider\n if (val !== FETCH.providerId) {\n fieldsToUnset.push('fetchProvider')\n if (NATIVE_FETCH_PROVIDERS.includes(val)) {\n issues.push({\n kind: 'user-override',\n field: 'fetchProvider',\n value: val,\n })\n } else {\n issues.push({\n kind: 'legacy-remnant',\n field: 'fetchProvider',\n value: val,\n })\n }\n }\n }\n }\n\n if (params.nativeSearchServed) {\n issues.push({\n kind: 'native-search-conflict',\n rowId: NATIVE_SEARCH_ROW,\n })\n }\n\n return {\n issues,\n fieldsToUnset,\n }\n}\n\n/**\n * Generate SettingsPathOpView array for resetting user-tier overrides on web row.\n */\nexport function buildUnsetOps(\n fields: readonly ('searchProvider' | 'fetchProvider')[],\n): SettingsPathOpView[] {\n return fields.map(field => ({\n op: 'unset',\n path: [field],\n }))\n}\n","import { Button, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PluginActivationOwnerProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { NS } from './locales.ts'\nimport type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { useObservable } from 'dsh-tool-web-enhanced-core/client'\nimport { checkUpgradePreflight } from './preflight.ts'\n\nexport type ActivationPromptProps = PluginActivationOwnerProps & PropsLocale<typeof NS> & {\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n}\n\nexport function ActivationPrompt({ onDismiss, onOpenDetails, webConfigForm, nativeSearchServed, t }: ActivationPromptProps) {\n const web = useObservable(webConfigForm)\n const preflight = checkUpgradePreflight({ user: web.user, nativeSearchServed })\n const hasIssues = preflight.issues.length > 0\n return (\n <Modal\n open\n title={t('activation.title')}\n closeLabel={t('activation.close')}\n onClose={onDismiss}\n footer={\n <>\n <Button variant=\"ghost\" onClick={onDismiss}>\n {t('activation.later')}\n </Button>\n <Button variant=\"primary\" data-modal-autofocus onClick={onOpenDetails}>\n {t('activation.open')}\n </Button>\n </>\n }\n >\n {hasIssues ? <p>{t('activation.preflight')}</p> : <>\n <p>{t('activation.body')}</p>\n <p>{t('activation.remoteOff')}</p>\n </>}\n </Modal>\n )\n}\n","import { FETCH, SEARCH, WEB_FIELD, routeOf, type Route } from 'dsh-tool-web-enhanced-core/shared'\nimport type { CapabilityName } from 'dsh-tool-web-enhanced-core/client'\nimport type { PluginRowRef } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\n\nexport interface WebConfigSnapshot {\n readonly [field: string]: unknown\n readonly searchProvider?: unknown\n readonly fetchProvider?: unknown\n}\n\nexport interface DisabledCapabilitiesResult {\n readonly searchDisabled: boolean\n readonly fetchDisabled: boolean\n readonly allDisabled: boolean\n}\n\nconst PROVIDER_ID = { search: SEARCH.providerId, fetch: FETCH.providerId } as const satisfies Record<CapabilityName, string>\n\n/**\n * Where a capability routes: the fact its plugin registered, or, without a\n * running plugin to register one, what the `web` row settings say.\n */\nexport function routeFor(capability: CapabilityName, routes: ReadonlyMap<CapabilityName, Route>, webConfig: WebConfigSnapshot | undefined): Route {\n const registered = routes.get(capability)\n return registered === undefined ? routeOf(webConfig, WEB_FIELD[capability], null, PROVIDER_ID[capability]) : registered\n}\n\n/**\n * Check whether routing targets an enhanced provider whose plugin is not served.\n * Prefer Host-aware facts; an absent plugin can only be judged from the web settings.\n */\nexport function checkDisabledCapabilities(params: {\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly routes: ReadonlyMap<CapabilityName, Route>\n}): DisabledCapabilitiesResult {\n const searchDisabled = routeFor('search', params.routes, params.webConfig).kind === 'this' && !params.searchServed\n const fetchDisabled = routeFor('fetch', params.routes, params.webConfig).kind === 'this' && !params.fetchServed\n\n const allDisabled = searchDisabled && fetchDisabled\n\n return {\n searchDisabled,\n fetchDisabled,\n allDisabled,\n }\n}\n\n/**\n * Pure function to check if a capability row is disabled in the bundle package rows.\n */\nexport function isCapabilityRowDisabled(params: {\n readonly rowId: string\n readonly rows: readonly PluginRowRef[]\n}): boolean {\n const row = params.rows.find(r => r.rowId === params.rowId)\n return row !== undefined && !row.enabled\n}\n","import {\n Fragment,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n IconCheckOutlineRegular,\n IconChevronDownOutlineRegular,\n IconChevronRightOutlineRegular,\n IconGlobeOutlineRegular,\n IconSettingsOutlineRegular,\n IconWarningOutlineRegular,\n MenuSurface,\n SegmentedTabs,\n StateDot,\n Toast,\n useDismissOnOutsidePointer,\n type SegmentedTab,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport { useObservable, type CapabilityName, type ConnectionSection, type SelectionState, type WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport { checkDisabledCapabilities, routeFor, type WebConfigSnapshot } from './disabled.ts'\nimport type { NS } from './locales.ts'\nimport type { Route } from 'dsh-tool-web-enhanced-core/shared'\nimport css from './ComposerConnectionMenu.module.css'\n\nfunction clsx(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ')\n}\n\nexport type Translate = TranslateNS<typeof NS>\n\n/** What one capability's side of the button and its section heading show. */\ntype SideState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'read-failed' }\n | { readonly kind: 'invalid-settings' }\n | { readonly kind: 'off' }\n | { readonly kind: 'missing' }\n | { readonly kind: 'connection'; readonly label: string; readonly ready: boolean }\n\nfunction sideState(section: ConnectionSection, state: SelectionState): SideState {\n if (state.readFailure === 'invalid-settings') return { kind: 'invalid-settings' }\n if (state.readFailure === 'failed') return { kind: 'read-failed' }\n const { view } = state\n if (view === undefined) return { kind: 'loading' }\n const { connectionId } = view.selection\n if (connectionId === null) return { kind: 'off' }\n const selected = view.connections.find(connection => connection.id === connectionId)\n if (selected === undefined) return { kind: 'missing' }\n return { kind: 'connection', label: section.describe(selected).label, ready: selected.status === 'ready' }\n}\n\nfunction sideText(side: SideState, t: Translate): string {\n switch (side.kind) {\n case 'loading': return t('button.loading')\n case 'read-failed': return t('button.readFailed')\n case 'invalid-settings': return t('button.invalidSettings')\n case 'off': return t('button.off')\n case 'missing': return t('button.missing')\n case 'connection': return side.label\n }\n}\n\n/** Whether the side needs the user: it cannot serve as shown, or the web row sends the capability elsewhere. */\nfunction needsAttention(side: SideState, route: Route): boolean {\n if (route.kind === 'other') return true\n switch (side.kind) {\n case 'loading':\n case 'off': return false\n case 'read-failed':\n case 'invalid-settings':\n case 'missing': return true\n case 'connection': return !side.ready\n }\n}\n\n/** One snapshot of several sources; the array stays the same while none of them changes. */\nfunction combineSnapshots<T>(sources: readonly ObservableSnapshot<T>[]): ObservableSnapshot<readonly T[]> {\n let last: readonly T[] = []\n return {\n getSnapshot() {\n const next = sources.map(source => source.getSnapshot())\n if (next.length !== last.length || next.some((value, index) => value !== last[index])) last = next\n return last\n },\n subscribe(listener) {\n const unsubscribes = sources.map(source => source.subscribe(listener))\n return () => {\n for (const unsubscribe of unsubscribes) unsubscribe()\n }\n },\n }\n}\n\nexport interface ModelSelectionProjection {\n readonly next?: { readonly provider: string; readonly model: string } | undefined\n}\n\nexport function modelKeyOf(projection: ModelSelectionProjection | undefined): string {\n const model = projection?.next\n return model ? `${model.provider}/${model.model}` : ''\n}\n\nfunction useMenuPosition({\n open,\n anchorRef,\n panelRef,\n rootRef,\n}: {\n open: boolean\n anchorRef: React.RefObject<HTMLElement | null>\n panelRef: React.RefObject<HTMLElement | null>\n rootRef: React.RefObject<HTMLElement | null>\n}): { left: number; top: number; maxWidth: number } | null {\n const [rawPosition, setRawPosition] = useState<{ left: number; top: number; maxWidth: number } | null>(null)\n\n useEffect(() => {\n if (!open) return\n\n const place = () => {\n const anchor = anchorRef.current\n if (!anchor) return\n const rect = anchor.getBoundingClientRect()\n const panel = panelRef.current\n const measuredWidth = panel?.offsetWidth ?? 0\n const height = panel?.offsetHeight ?? 0\n\n // Main content area left boundary (e.g. conversation session container)\n const mainArea =\n rootRef.current?.closest('[data-conversation-session]') ??\n document.querySelector('[data-conversation-session]') ??\n document.querySelector('main')\n const mainLeft = mainArea ? mainArea.getBoundingClientRect().left : 12\n const minLeft = Math.min(Math.max(12, mainLeft), window.innerWidth - 12)\n const maxWidth = Math.max(0, window.innerWidth - minLeft - 12)\n const width = Math.min(measuredWidth, maxWidth)\n\n let left = rect.right - width\n // If overflowing left boundary, check if flipping to start fits better\n if (left < minLeft && rect.left + width <= window.innerWidth - 12) {\n left = rect.left\n }\n if (width > 0) {\n const maxLeft = Math.max(minLeft, window.innerWidth - width - 12)\n left = Math.min(Math.max(left, minLeft), maxLeft)\n }\n\n // Vertical placement: side='top', gap=8\n let top = rect.top - 8 - height\n if (top < 12 && rect.bottom + 8 + height <= window.innerHeight - 12) {\n top = rect.bottom + 8\n }\n if (height > 0) {\n top = Math.min(Math.max(top, 12), Math.max(12, window.innerHeight - height - 12))\n }\n\n setRawPosition({ left, top, maxWidth })\n }\n\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n\n let observer: ResizeObserver | null = null\n if (typeof ResizeObserver !== 'undefined' && panelRef.current) {\n observer = new ResizeObserver(place)\n observer.observe(panelRef.current)\n }\n\n return () => {\n observer?.disconnect()\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [open, anchorRef, panelRef, rootRef])\n\n return open ? rawPosition : null\n}\n\nexport interface ComposerConnectionMenuProps {\n readonly sessionId: string\n readonly modelKey?: string | undefined\n readonly webConnections: WebConnectionsService\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly onOpenPlugins?: (() => void) | undefined\n readonly t: Translate\n}\n\nexport function ComposerConnectionMenu({\n sessionId,\n modelKey,\n webConnections,\n searchServed,\n fetchServed,\n webConfig,\n onOpenPlugins,\n t,\n}: ComposerConnectionMenuProps) {\n const sections = useObservable(webConnections.sections)\n const routes = useObservable(webConnections.routes)\n\n if (sections.length === 0) {\n return null\n }\n\n return (\n <ComposerConnectionMenuInner\n sessionId={sessionId}\n modelKey={modelKey}\n sections={sections}\n routes={routes}\n searchServed={searchServed}\n fetchServed={fetchServed}\n webConfig={webConfig}\n onOpenPlugins={onOpenPlugins}\n t={t}\n />\n )\n}\n\nfunction ComposerConnectionMenuInner({\n sessionId,\n modelKey,\n sections,\n routes,\n searchServed,\n fetchServed,\n webConfig,\n onOpenPlugins,\n t,\n}: {\n readonly sessionId: string\n readonly modelKey?: string | undefined\n readonly sections: readonly ConnectionSection[]\n readonly routes: ReadonlyMap<CapabilityName, Route>\n readonly searchServed: boolean\n readonly fetchServed: boolean\n readonly webConfig?: WebConfigSnapshot | undefined\n readonly onOpenPlugins?: (() => void) | undefined\n readonly t: Translate\n}) {\n const [open, setOpen] = useState(false)\n // The capability whose panel the menu shows; the menu opens on the first.\n const [selected, setSelected] = useState<CapabilityName | null>(null)\n const [notice, setNotice] = useState<{ seq: number; text: string } | null>(null)\n const [rootEl, setRootEl] = useState<HTMLDivElement | null>(null)\n const seqRef = useRef(0)\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const id = useId()\n\n const position = useMenuPosition({\n open,\n anchorRef: triggerRef,\n panelRef: menuRef,\n rootRef,\n })\n useDismissOnOutsidePointer(rootRef, open, setOpen, menuRef)\n\n // A dialog takes focus: the selected tab, once the placed menu is visible and focusable.\n const placed = position !== null\n useEffect(() => {\n if (!placed) return\n menuRef.current?.querySelector<HTMLElement>('[role=\"tab\"][aria-selected=\"true\"]')?.focus({ preventScroll: true })\n }, [placed])\n\n const sortedSections = useMemo(() => sections.toSorted((a, b) => a.order - b.order), [sections])\n const states = useObservable(useMemo(\n () => combineSnapshots(sortedSections.map(section => section.selection.source(sessionId))),\n [sortedSections, sessionId],\n ))\n\n useEffect(() => {\n for (const section of sections) {\n void section.selection.load(sessionId, modelKey)\n }\n }, [sections, sessionId, modelKey])\n\n const close = (): void => {\n setOpen(false)\n triggerRef.current?.focus()\n }\n\n const onTriggerClick = (): void => {\n if (open) {\n close()\n } else {\n setOpen(true)\n setSelected(sortedSections[0]!.capability)\n for (const section of sections) {\n void section.selection.load(sessionId, modelKey)\n }\n }\n }\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n if (!open || event.nativeEvent.isComposing) return\n if (event.key === 'Escape') {\n event.preventDefault()\n close()\n }\n }\n\n const choose = async (section: ConnectionSection, connectionId: string | null): Promise<void> => {\n const currentView = section.selection.source(sessionId).getSnapshot().view\n if (currentView?.selection.connectionId === connectionId) {\n close()\n return\n }\n\n const res = await section.selection.set(sessionId, { connectionId })\n if (!res.ok) {\n setNotice({ seq: seqRef.current++, text: section.writeFailureText(res.error) })\n } else {\n close()\n }\n }\n\n // Each side shows its connection; other states name their side, since \"Off\" alone does not say which.\n const sides = sortedSections.map((section, index) => {\n const side = sideState(section, states[index]!)\n const state = sideText(side, t)\n const capability = section.title()\n const attention = needsAttention(side, routeFor(section.capability, routes, webConfig))\n return {\n section,\n capability: section.capability,\n label: side.kind === 'connection' ? state : t('button.side', { capability, state }),\n name: t(attention ? 'button.sideAttention' : 'button.side', { capability, state }),\n attention,\n }\n })\n const triggerName = sides.map(side => side.name).join(' · ')\n const saving = states.some(state => state.saving)\n\n // A section that went away while the menu was open hands the panel to the first.\n const active = sortedSections.find(section => section.capability === selected) ?? sortedSections[0]!\n const tabId = (capability: CapabilityName): string => `${id}-tab-${capability}`\n const panelId = (capability: CapabilityName): string => `${id}-panel-${capability}`\n const [firstTab, ...otherTabs] = sides.map((side): SegmentedTab<CapabilityName> => ({\n value: side.capability,\n id: tabId(side.capability),\n panelId: panelId(side.capability),\n label: (\n <span className={css.tabLabel} title={side.name}>\n <span className={css.tabTitle}>{side.section.title()}</span>\n {side.attention && <StateDot state=\"warning\" className={css.tabMark} />}\n </span>\n ),\n }))\n\n const disabled = checkDisabledCapabilities({\n searchServed,\n fetchServed,\n webConfig,\n routes,\n })\n const unavailable = [\n ...(disabled.searchDisabled ? [t('disabled.search')] : []),\n ...(disabled.fetchDisabled ? [t('disabled.fetch')] : []),\n ]\n\n return (\n <div\n ref={el => {\n rootRef.current = el\n setRootEl(el)\n }}\n className={css.root}\n onKeyDown={onKeyDown}\n >\n <button\n ref={triggerRef}\n type=\"button\"\n className={css.trigger}\n aria-label={triggerName}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? `${id}-menu` : undefined}\n title={triggerName}\n onClick={onTriggerClick}\n >\n <span className={css.icon}>\n <IconGlobeOutlineRegular size={16} />\n {/* The compact display: the labels are hidden, so each side's mark sits on the globe. */}\n <span className={css.iconMarks}>\n {sides.map(side => side.attention && (\n <span key={side.capability} className={css.iconMark} data-mark={side.capability}>\n <StateDot state=\"warning\" />\n </span>\n ))}\n </span>\n </span>\n <span className={css.labels}>\n <span className={css.sides}>\n {sides.map((side, index) => (\n <Fragment key={side.capability}>\n {index > 0 && <span className={css.sideSeparator} aria-hidden=\"true\">·</span>}\n <span className={css.side} data-capability={side.capability}>\n <span className={css.sideLabel}>{side.label}</span>\n {side.attention && <StateDot state=\"warning\" className={css.sideMark} />}\n </span>\n </Fragment>\n ))}\n </span>\n </span>\n {saving ? (\n <StateDot state=\"ongoing\" className={css.busy} />\n ) : (\n <IconChevronDownOutlineRegular\n size={12}\n className={clsx(css.chevron, open && css.chevronOpen)}\n />\n )}\n </button>\n\n {open &&\n createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={css.menu}\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n aria-label={t('menu.aria')}\n >\n {/* Every panel shares one grid cell: the menu keeps the tallest one's height while switching. */}\n <div className={css.panels}>\n {sortedSections.map(section => (\n <SectionPanel\n key={section.capability}\n section={section}\n route={routeFor(section.capability, routes, webConfig)}\n sessionId={sessionId}\n active={section === active}\n tabId={tabId(section.capability)}\n panelId={panelId(section.capability)}\n onChoose={connId => void choose(section, connId)}\n onCloseMenu={close}\n t={t}\n />\n ))}\n </div>\n\n {unavailable.length > 0 && (\n <div className={css.notices}>\n {unavailable.map(text => (\n <div key={text} className={css.disabledNotice} role=\"status\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <div>\n <div>{text}</div>\n {onOpenPlugins !== undefined && (\n <button\n type=\"button\"\n className={css.linkAction}\n onClick={() => {\n close()\n onOpenPlugins()\n }}\n >\n {t('disabled.openPlugins')}\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* The bottom layer, nearest the button: which capability the panel above shows. */}\n <div className={css.switcher}>\n <SegmentedTabs\n items={[firstTab!, ...otherTabs]}\n value={active.capability}\n onChange={setSelected}\n label={t('menu.tabs')}\n />\n </div>\n </MenuSurface>,\n document.body,\n )}\n\n {notice !== null && (\n <Toast\n key={notice.seq}\n text={notice.text}\n icon={<IconWarningOutlineRegular />}\n holdMs={4000}\n anchor={rootEl}\n onDone={() => setNotice(null)}\n />\n )}\n </div>\n )\n}\n\nfunction SectionPanel({\n section,\n route,\n sessionId,\n active,\n tabId,\n panelId,\n onChoose,\n onCloseMenu,\n t,\n}: {\n readonly section: ConnectionSection\n readonly route: Route\n readonly sessionId: string\n readonly active: boolean\n readonly tabId: string\n readonly panelId: string\n readonly onChoose: (connectionId: string | null) => void\n readonly onCloseMenu: () => void\n readonly t: Translate\n}) {\n const state = useObservable(section.selection.source(sessionId))\n const settingsFn = useObservable(section.settings)\n const remoteServicesOff = useObservable(section.remoteServicesOff)\n const bodyRef = useRef<HTMLDivElement | null>(null)\n\n const view = state.view\n const loaded = view !== undefined\n\n // Showing a panel, or its list arriving while shown, brings the chosen row into view.\n useEffect(() => {\n if (!active || !loaded) return\n bodyRef.current?.querySelector('[aria-checked=\"true\"]')?.scrollIntoView({ block: 'nearest' })\n }, [active, loaded])\n\n const current = sideText(sideState(section, state), t)\n // A failed read leaves no current source to name.\n const source = view !== undefined && state.readFailure === undefined ? section.sourceText(view) : ''\n const summaryId = panelId + '-summary'\n // Connections turned off in settings are not offered; the Session's own choice stays, so its check and warning have a row.\n const listed = view === undefined ? [] : view.connections.filter(conn => conn.status !== 'disabled' || conn.id === view.selection.connectionId)\n\n return (\n <div\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-describedby={summaryId}\n // Hidden panels keep their size so the menu does not jump; they leave the tab order and the accessibility tree.\n aria-hidden={active ? undefined : true}\n className={clsx(css.panel, !active && css.panelInactive)}\n >\n <div className={css.panelHeader}>\n <p id={summaryId} className={css.summary} title={[current, source].filter(Boolean).join(' · ')}>\n <span className={css.summaryCurrent}>{current}</span>\n {source && (\n <>\n <span className={css.summarySeparator} aria-hidden=\"true\">·</span>\n <span className={css.summarySource}>{source}</span>\n </>\n )}\n </p>\n {/* An icon, so the summary keeps the header's width. */}\n {settingsFn !== undefined && (\n <button\n type=\"button\"\n className={css.settingsButton}\n aria-label={t('menu.settings')}\n title={t('menu.settings')}\n onClick={() => {\n onCloseMenu()\n settingsFn()\n }}\n >\n <IconSettingsOutlineRegular size={14} />\n </button>\n )}\n </div>\n\n <div ref={bodyRef} className={css.panelBody}>\n {route.kind === 'other' && (\n <div className={css.routeNotice} role=\"alert\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <span>{t('menu.routeWarning', { provider: route.provider })}</span>\n </div>\n )}\n\n {state.readFailure === 'invalid-settings' ? (\n // Retrying cannot help: the settings must be fixed, through the settings entry above.\n <div className={css.routeNotice} role=\"alert\">\n <IconWarningOutlineRegular size={14} className={css.noticeIcon} />\n <span>{t('menu.invalidSettings', { capability: section.title() })}</span>\n </div>\n ) : view === undefined ? (\n state.readFailure === 'failed' ? (\n <button\n type=\"button\"\n className={css.row}\n onClick={() => {\n void section.selection.load(sessionId)\n }}\n >\n <span className={clsx(css.rowLabel, css.rowCaptionWarn)}>\n {t('button.readFailed')}\n </span>\n </button>\n ) : (\n <div className={css.empty}>{t('button.loading')}</div>\n )\n ) : (\n <>\n <div role=\"menu\" aria-label={section.title()}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={view.selection.connectionId === null}\n className={css.row}\n disabled={state.saving}\n onClick={() => onChoose(null)}\n >\n <span className={css.rowLabel}>{t('menu.offRow')}</span>\n <span className={css.check}>\n {view.selection.connectionId === null && <IconCheckOutlineRegular size={14} />}\n </span>\n </button>\n\n {listed.map(conn => {\n const text = section.describe(conn)\n const isSelected = conn.id === view.selection.connectionId\n const isReady = conn.status === 'ready'\n const canOpenSettings = !isReady && settingsFn !== undefined\n\n const onClick = () => {\n if (canOpenSettings) {\n onCloseMenu()\n settingsFn()\n } else if (isReady) {\n onChoose(conn.id)\n }\n }\n\n return (\n <button\n key={conn.id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isSelected}\n className={css.row}\n disabled={isReady ? state.saving : !canOpenSettings}\n title={text.reason ?? text.label}\n onClick={onClick}\n >\n <div className={css.rowContent}>\n <span className={css.rowLabel}>{text.label}</span>\n {text.caption && !text.reason && (\n <span className={css.rowCaption}>{text.caption}</span>\n )}\n {text.reason && (\n <span className={clsx(css.rowCaption, css.rowCaptionWarn)}>\n <span className={css.warnDot} aria-hidden=\"true\" />\n <span>{text.reason}</span>\n </span>\n )}\n </div>\n <span className={css.check}>\n {isSelected && <IconCheckOutlineRegular size={14} />}\n </span>\n </button>\n )\n })}\n </div>\n\n {listed.length === 0 && <div className={css.empty}>{t('menu.empty')}</div>}\n\n {section.Options && (\n <div className={css.optionsWrapper}>\n <section.Options sessionId={sessionId} />\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Outside the scrolling list, so it stays at the panel's foot. */}\n {remoteServicesOff && (\n <div className={css.panelFooter}>\n {settingsFn === undefined ? (\n <span className={css.footerText}>{t('menu.moreServices')}</span>\n ) : (\n <button\n type=\"button\"\n className={css.footerAction}\n onClick={() => {\n onCloseMenu()\n settingsFn()\n }}\n >\n <span>{t('menu.moreServices')}</span>\n <IconChevronRightOutlineRegular size={12} className={css.footerIcon} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n </div>\n )\n}\n","export const NS = 'tool-web-enhanced-ui' as const\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'button.title': '网页连接',\n 'button.aria': '选择网页连接',\n 'button.loading': '正在加载…',\n 'button.readFailed': '读取失败',\n 'button.missing': '连接已移除',\n 'button.off': '已关闭',\n 'button.invalidSettings': '设置无效',\n 'button.side': '{capability}:{state}',\n 'button.sideAttention': '{capability}:{state}(需要处理)',\n 'menu.aria': '网页连接菜单',\n 'menu.tabs': '网页能力',\n 'menu.offRow': '关闭',\n 'menu.empty': '没有可用的连接',\n 'menu.settings': '设置',\n 'menu.routeWarning': '当前由 {provider} 提供,这里的选择不会生效。',\n 'menu.invalidSettings': '{capability}的设置无效,请打开设置修复。',\n 'menu.moreServices': '更多服务可在设置中打开',\n \"disabled.search\": \"网页搜索暂不可用:增强网页搜索已停用,请在上方启用。\",\n \"disabled.fetch\": \"网页获取暂不可用:增强网页获取已停用,请在上方启用。\",\n 'disabled.openPlugins': '打开插件页',\n 'activation.title': '增强网页工具已启用',\n \"activation.body\": \"网页搜索和网页获取现在由本组合包的插件提供。点输入框右侧的地球按钮为每个会话选择连接;连接、密钥和默认值在插件设置里配置。\",\n 'activation.remoteOff': '远程服务默认关闭,需要时也在那里打开。',\n 'activation.preflight': '之前的设置可能让本组合包无法接管网页工具。请打开设置查看详情,并按提示移除遗留设置。',\n 'activation.later': '稍后',\n 'activation.open': '打开设置',\n 'activation.close': '关闭',\n 'overview.title': '网页工具状态',\n \"overview.description\": \"网页搜索与网页获取由谁提供,以及从 0.1.x 升级后遗留的设置。\",\n 'overview.search.title': '网页搜索',\n 'overview.fetch.title': '网页获取',\n 'overview.status.routed': '由增强网页搜索提供',\n 'overview.status.routedFetch': '由增强网页获取提供',\n 'overview.status.notRouted': '未由增强网页搜索提供',\n 'overview.status.notRoutedFetch': '未由增强网页获取提供',\n 'overview.status.rowDisabled': '已关闭',\n 'overview.status.effective': '当前生效:{provider}',\n 'overview.status.base': '组合包默认:{provider}',\n 'overview.status.user': '你的设置:{provider}',\n 'overview.status.none': '未设置',\n 'preflight.title': '升级检查',\n 'preflight.healthy': '没有发现遗留设置。',\n 'preflight.userOverride': '你的设置把 {tool} 交给了 {value},不再经过本组合包。',\n 'preflight.legacyRemnant': '{tool} 仍指向 0.1.x 留下的、已不存在的 provider,{action}会失败。',\n 'preflight.action.searchAction': '搜索',\n 'preflight.action.fetchAction': '获取网页',\n 'preflight.nativeSearchConflict': '内置的 DeepSeek 网页搜索插件已重新开启,可能接管网页搜索。不需要时请关闭它。',\n 'preflight.action.fix': '移除遗留设置',\n 'preflight.confirm.title': '移除遗留设置',\n 'preflight.confirm.body': '将从你的设置中移除 {fields},恢复本组合包 的选择。',\n 'preflight.confirm.confirm': '移除',\n 'preflight.confirm.cancel': '取消',\n 'preflight.confirm.close': '关闭',\n 'preflight.action.success': '已移除设置',\n 'preflight.action.failed': '未修改:设置可能已在别处更改,请重试。',\n} satisfies Record<string, string>\n\nexport type LocaleKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'button.title': 'Web connections',\n 'button.aria': 'Choose web connections',\n 'button.loading': 'Loading…',\n 'button.readFailed': \"Couldn't load\",\n 'button.missing': 'Connection removed',\n 'button.off': 'Off',\n 'button.invalidSettings': 'Invalid settings',\n 'button.side': '{capability}: {state}',\n 'button.sideAttention': '{capability}: {state} (needs attention)',\n 'menu.aria': 'Web connections menu',\n 'menu.tabs': 'Web capabilities',\n 'menu.offRow': 'Off',\n 'menu.empty': 'No connections available',\n 'menu.settings': 'Settings',\n 'menu.routeWarning': 'Served by {provider}; choices here have no effect.',\n 'menu.invalidSettings': '{capability} settings are invalid. Open settings to fix them.',\n 'menu.moreServices': 'More services can be turned on in settings',\n \"disabled.search\": \"Web search isn't available because Web Search Enhanced is off. Turn it on above.\",\n \"disabled.fetch\": \"Web fetch isn't available because Web Fetch Enhanced is off. Turn it on above.\",\n 'disabled.openPlugins': 'Open Plugins page',\n 'activation.title': 'Web Tools Enhanced is enabled',\n \"activation.body\": \"Web search and web fetch now go through this bundle's plugins. Pick a connection for each conversation with the globe button in the composer; set up connections, keys and defaults in the plugin settings.\",\n 'activation.remoteOff': 'Remote services are off by default; turn them on there when you need them.',\n 'activation.preflight': 'Some previous settings may stop this bundle from handling web tools. Open settings to review them and remove leftover settings.',\n 'activation.later': 'Later',\n 'activation.open': 'Open settings',\n 'activation.close': 'Close',\n 'overview.title': 'Web tools status',\n \"overview.description\": \"Which service handles web search and web fetch, and settings left over from 0.1.x.\",\n 'overview.search.title': 'Web search',\n 'overview.fetch.title': 'Web fetch',\n 'overview.status.routed': 'Served by Web Search Enhanced',\n 'overview.status.routedFetch': 'Served by Web Fetch Enhanced',\n 'overview.status.notRouted': 'Not served by Web Search Enhanced',\n 'overview.status.notRoutedFetch': 'Not served by Web Fetch Enhanced',\n 'overview.status.rowDisabled': 'Off',\n 'overview.status.effective': 'Effective: {provider}',\n 'overview.status.base': 'Bundle default: {provider}',\n 'overview.status.user': 'Your setting: {provider}',\n 'overview.status.none': 'Not set',\n 'preflight.title': 'Upgrade check',\n 'preflight.healthy': 'No leftover settings found.',\n 'preflight.userOverride': 'Your settings route {tool} to {value}, so it bypasses this bundle.',\n 'preflight.legacyRemnant': '{tool} is set to a provider from 0.1.x that no longer exists, so {action} fail.',\n 'preflight.action.searchAction': 'searches',\n 'preflight.action.fetchAction': 'fetches',\n 'preflight.nativeSearchConflict': 'The built-in DeepSeek web search plugin is on again and can take over web search. Turn it off unless you need it.',\n 'preflight.action.fix': 'Remove leftover settings',\n 'preflight.confirm.title': 'Remove leftover settings',\n 'preflight.confirm.body': \"This removes {fields} from your settings and restores this bundle's choice.\",\n 'preflight.confirm.confirm': 'Remove',\n 'preflight.confirm.cancel': 'Cancel',\n 'preflight.confirm.close': 'Close',\n 'preflight.action.success': 'Settings removed',\n 'preflight.action.failed': 'Not changed. The settings may have changed elsewhere; try again.',\n} satisfies Record<LocaleKey, string>\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'tool-web-enhanced-ui': LocaleKey\n }\n}\n","import { useState } from 'react'\nimport {\n Button,\n IconCheckOutlineRegular,\n IconWarningOutlineRegular,\n Modal,\n StateDot,\n Toast,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PluginDetailProps, PluginsSubject } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type { ConfigForm, ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { PropsLocale, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport { FETCH, PROFILE_PACKAGE, SEARCH, WEB_FIELD, isRouted, type Route } from 'dsh-tool-web-enhanced-core/shared'\nimport { useObservable, type CapabilityName, type WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport { isCapabilityRowDisabled, routeFor } from './disabled.ts'\nimport type { NS } from './locales.ts'\nimport { buildUnsetOps, checkUpgradePreflight } from './preflight.ts'\nimport css from './ProfileDetailSection.module.css'\n\nexport type Translate = TranslateNS<typeof NS>\n\nexport interface ProfileDetailSectionProps extends PluginDetailProps, PropsLocale<typeof NS> {\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n readonly webConnections: WebConnectionsService\n}\n\nexport function ProfileDetailSection({\n subject,\n webConfigForm,\n nativeSearchServed,\n webConnections,\n t,\n}: ProfileDetailSectionProps) {\n if (subject.kind !== 'bundle' || subject.pkg.name !== PROFILE_PACKAGE) {\n return null\n }\n\n return (\n <ProfileDetailSectionInner\n subject={subject}\n webConfigForm={webConfigForm}\n nativeSearchServed={nativeSearchServed}\n webConnections={webConnections}\n t={t}\n />\n )\n}\n\nfunction ProfileDetailSectionInner({\n subject,\n webConfigForm,\n nativeSearchServed,\n webConnections,\n t,\n}: {\n readonly subject: Extract<PluginsSubject, { kind: 'bundle' }>\n readonly webConfigForm: ConfigForm<Record<string, unknown>>\n readonly nativeSearchServed: boolean\n readonly webConnections: WebConnectionsService\n readonly t: Translate\n}) {\n const [confirmOpen, setConfirmOpen] = useState(false)\n const [mutating, setMutating] = useState(false)\n const [toast, setToast] = useState<{ text: string; ok: boolean } | null>(null)\n\n const webSnapshot = useObservable(webConfigForm)\n const routes = useObservable(webConnections.routes)\n\n const preflight = checkUpgradePreflight({\n user: webSnapshot.user,\n nativeSearchServed,\n })\n\n const healthy = preflight.issues.length === 0\n const canFix = preflight.fieldsToUnset.length > 0\n const lastFixableIssue = preflight.issues.findLast(issue => issue.kind !== 'native-search-conflict')\n\n const onConfirmReset = async (): Promise<void> => {\n if (preflight.fieldsToUnset.length === 0) return\n setMutating(true)\n try {\n const ops = buildUnsetOps(preflight.fieldsToUnset)\n const ok = await webConfigForm.mutate(ops, webSnapshot.revision)\n setToast({\n text: t(ok ? 'preflight.action.success' : 'preflight.action.failed'),\n ok,\n })\n } finally {\n setMutating(false)\n setConfirmOpen(false)\n }\n }\n\n return (\n <section className={css.section} aria-label={t('overview.title')}>\n <div className={css.header}>\n <h3 className={css.title}>{t('overview.title')}</h3>\n <p className={css.description}>{t('overview.description')}</p>\n </div>\n\n <div className={css.container}>\n <CapabilityCard\n title={t('overview.search.title')}\n capability=\"search\"\n providerId={SEARCH.providerId}\n rowDisabled={isCapabilityRowDisabled({ rowId: SEARCH.rowId, rows: subject.pkg.rows })}\n webSnapshot={webSnapshot}\n routes={routes}\n t={t}\n />\n <CapabilityCard\n title={t('overview.fetch.title')}\n capability=\"fetch\"\n providerId={FETCH.providerId}\n rowDisabled={isCapabilityRowDisabled({ rowId: FETCH.rowId, rows: subject.pkg.rows })}\n webSnapshot={webSnapshot}\n routes={routes}\n t={t}\n />\n\n {/* Upgrade Preflight Row */}\n <div className={css.preflightBox}>\n <div className={css.preflightHeader}>\n <span className={css.preflightTitle}>{t('preflight.title')}</span>\n </div>\n\n {healthy ? (\n <div className={css.healthyText}>{t('preflight.healthy')}</div>\n ) : (\n <div className={css.issuesList}>\n {preflight.issues.map((issue, idx) => (\n <div key={idx} className={css.issueItem}>\n <IconWarningOutlineRegular className={css.issueIcon} size={16} />\n <div>\n <span>\n {issue.kind === 'user-override' &&\n t('preflight.userOverride', {\n tool: t(issue.field === 'searchProvider' ? 'overview.search.title' : 'overview.fetch.title'),\n value: issue.value,\n })}\n {issue.kind === 'legacy-remnant' &&\n t('preflight.legacyRemnant', {\n tool: t(issue.field === 'searchProvider' ? 'overview.search.title' : 'overview.fetch.title'),\n action:\n issue.field === 'searchProvider'\n ? t('preflight.action.searchAction')\n : t('preflight.action.fetchAction'),\n })}\n {issue.kind === 'native-search-conflict' &&\n t('preflight.nativeSearchConflict')}\n </span>\n {canFix && issue === lastFixableIssue && (\n <div className={css.fixableActionRow}>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setConfirmOpen(true)}>\n {t('preflight.action.fix')}\n </Button>\n </div>\n )}\n </div>\n </div>\n ))}\n\n\n </div>\n )}\n </div>\n </div>\n\n {confirmOpen && (\n <Modal\n open\n title={t('preflight.confirm.title')}\n closeLabel={t('preflight.confirm.close')}\n onClose={() => setConfirmOpen(false)}\n footer={\n <>\n <Button variant=\"ghost\" onClick={() => setConfirmOpen(false)}>\n {t('preflight.confirm.cancel')}\n </Button>\n <Button\n variant=\"primary\"\n disabled={mutating}\n onClick={() => void onConfirmReset()}\n >\n {t('preflight.confirm.confirm')}\n </Button>\n </>\n }\n >\n <p>{t('preflight.confirm.body', { fields: preflight.fieldsToUnset.join(', ') })}</p>\n </Modal>\n )}\n\n {toast !== null && (\n <Toast\n text={toast.text}\n icon={toast.ok ? <IconCheckOutlineRegular /> : <IconWarningOutlineRegular />}\n holdMs={3000}\n onDone={() => setToast(null)}\n />\n )}\n </section>\n )\n}\n\nfunction RouteBadge({ capability, route, rowDisabled, t }: {\n readonly capability: 'search' | 'fetch'\n readonly route: Route\n readonly rowDisabled: boolean\n readonly t: Translate\n}) {\n const routed = isRouted(route)\n const routedKey = capability === 'search' ? 'overview.status.routed' : 'overview.status.routedFetch'\n const notRoutedKey = capability === 'search' ? 'overview.status.notRouted' : 'overview.status.notRoutedFetch'\n const key = rowDisabled ? 'overview.status.rowDisabled' : routed ? routedKey : notRoutedKey\n const healthy = routed && !rowDisabled\n return (\n <span className={healthy ? css.routedBadge : css.notRoutedBadge}>\n <StateDot state={healthy ? 'done' : 'warning'} />\n {t(key)}\n </span>\n )\n}\n\nfunction renderProviderLine(labelTemplate: string, provider: string, noneText: string) {\n const parts = labelTemplate.split('{provider}')\n if (parts.length === 1) return <span>{labelTemplate}</span>\n return (\n <span>\n {parts[0]}\n {provider === noneText ? provider : <code>{provider}</code>}\n {parts[1]}\n </span>\n )\n}\n\nfunction CapabilityCard({\n title,\n capability,\n providerId,\n rowDisabled,\n webSnapshot,\n routes,\n t,\n}: {\n readonly title: string\n readonly capability: CapabilityName\n readonly providerId: string\n readonly rowDisabled: boolean\n readonly webSnapshot: ConfigFormSnapshot<Record<string, unknown>>\n readonly routes: ReadonlyMap<CapabilityName, Route>\n readonly t: Translate\n}) {\n const field = WEB_FIELD[capability]\n const webBase = (typeof webSnapshot.base === 'object' && webSnapshot.base !== null ? webSnapshot.base : {}) as Record<string, unknown>\n const webUser = (typeof webSnapshot.user === 'object' && webSnapshot.user !== null ? webSnapshot.user : {}) as Record<string, unknown>\n const currentRoute = routeFor(capability, routes, webSnapshot.value)\n\n const noneText = t('overview.status.none')\n\n const effectiveProvider = currentRoute.kind === 'this' ? providerId : currentRoute.kind === 'other' ? currentRoute.provider : noneText\n const baseProvider = typeof webBase[field] === 'string' ? webBase[field] : noneText\n const userProvider = typeof webUser[field] === 'string' ? webUser[field] : noneText\n\n return (\n <div className={css.card}>\n <div className={css.cardHeader}>\n <span className={css.cardTitle}>{title}</span>\n <RouteBadge\n capability={capability}\n route={currentRoute}\n rowDisabled={rowDisabled}\n t={t}\n />\n </div>\n\n <div className={css.statusList}>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.effective'), effectiveProvider, noneText)}\n </div>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.base'), baseProvider, noneText)}\n </div>\n <div className={css.statusItem}>\n {renderProviderLine(t('overview.status.user'), userProvider, noneText)}\n </div>\n </div>\n\n {rowDisabled && (\n <div className={css.warnBox}>\n <IconWarningOutlineRegular size={14} className={css.warnIcon} />\n <span>{t(field === 'searchProvider' ? 'disabled.search' : 'disabled.fetch')}</span>\n </div>\n )}\n </div>\n )\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'\nimport type { CapabilityName, ConnectionSection, RouteStore, WebConnectionsService } from 'dsh-tool-web-enhanced-core/client'\nimport type { Route } from 'dsh-tool-web-enhanced-core/shared'\n\nexport { createSnapshotStore }\n\n/**\n * Pure factory for the WebConnectionsService interface.\n */\nexport function createWebConnectionsService(): WebConnectionsService {\n const store = createSnapshotStore<readonly ConnectionSection[]>([])\n const registered = new Set<ConnectionSection>()\n const routes = createSnapshotStore<ReadonlyMap<CapabilityName, Route>>(new Map())\n const routeSources = new Set<{ readonly capability: CapabilityName; readonly route: RouteStore }>()\n\n const publishRoutes = (): void => {\n const next = new Map<CapabilityName, Route>()\n for (const entry of routeSources) next.set(entry.capability, entry.route.source.getSnapshot())\n routes.set(next)\n }\n\n const publish = (): void => {\n const sorted = [...registered].toSorted((a, b) => a.order - b.order)\n store.set(sorted)\n }\n\n return {\n routes,\n registerRoute(capability, route) {\n const entry = { capability, route }\n routeSources.add(entry)\n const unsubscribe = route.source.subscribe(publishRoutes)\n publishRoutes()\n return () => {\n if (!routeSources.delete(entry)) return\n unsubscribe()\n publishRoutes()\n }\n },\n get sections(): ObservableSnapshot<readonly ConnectionSection[]> {\n return store\n },\n register(section: ConnectionSection): () => void {\n registered.add(section)\n publish()\n return () => {\n if (registered.delete(section)) {\n publish()\n }\n }\n },\n }\n}\n\n/**\n * Installs the webConnections service on a Cordis Context.\n */\nexport function installWebConnectionsService(ctx: Context): WebConnectionsService {\n const service = createWebConnectionsService()\n ctx.provide('webConnections', service)\n return service\n}\n","/**\n * Browser face of dsh-tool-web-enhanced-ui:\n * - webConnections browser service (registry for connection sections)\n * - conversation.input.right: single web connection button and dropdown menu\n * - plugins.bundle.activation: activation guidance modal for the profile bundle\n * - plugins.detail.section: profile bundle overview and upgrade preflight\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { PluginActivationOwnerProps, PluginDetailProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-plugin-manager/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { FETCH, PROFILE_PACKAGE, SEARCH, UI } from 'dsh-tool-web-enhanced-core/shared'\nimport { useObservable } from 'dsh-tool-web-enhanced-core/client'\nimport { ActivationPrompt } from './ActivationPrompt.tsx'\nimport { ComposerConnectionMenu, modelKeyOf } from './ComposerConnectionMenu.tsx'\nimport { en, NS, zh } from './locales.ts'\nimport { NATIVE_SEARCH_ROW } from './preflight.ts'\nimport { ProfileDetailSection } from './ProfileDetailSection.tsx'\nimport { createSnapshotStore, installWebConnectionsService } from './service.ts'\n\nexport const inject = ['slots', 'locale', 'configForms']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'tool-web-enhanced-ui: dictionaries')\n\n const webConnections = installWebConnectionsService(ctx)\n const webConfigForm = ctx.configForms.get<Record<string, unknown>>('web')\n\n let searchServed = false\n let fetchServed = false\n let nativeSearchServed = false\n\n const servedStore = createSnapshotStore({\n searchServed: false,\n fetchServed: false,\n nativeSearchServed: false,\n })\n\n const syncServed = (): void => {\n servedStore.set({ searchServed, fetchServed, nativeSearchServed })\n }\n\n // Check whileServed for search and fetch\n ctx.effect(\n () =>\n ctx.configForms.whileServed([SEARCH.rowId], () => {\n searchServed = true\n syncServed()\n return () => {\n searchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed search',\n )\n\n ctx.effect(\n () =>\n ctx.configForms.whileServed([FETCH.rowId], () => {\n fetchServed = true\n syncServed()\n return () => {\n fetchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed fetch',\n )\n\n ctx.effect(\n () =>\n ctx.configForms.whileServed([NATIVE_SEARCH_ROW], () => {\n nativeSearchServed = true\n syncServed()\n return () => {\n nativeSearchServed = false\n syncServed()\n }\n }),\n 'tool-web-enhanced-ui: whileServed native search',\n )\n\n // The store holds an object, never the bare callback: `set(fn)` would run `fn` as an updater.\n const openPluginsStore = createSnapshotStore<{ readonly open: (() => void) | undefined }>({ open: undefined })\n ctx.inject(['pluginNavigation'], scope => {\n scope.effect(() => {\n openPluginsStore.set({ open: () => { scope.pluginNavigation.openBundle(PROFILE_PACKAGE) } })\n return () => {\n openPluginsStore.set({ open: undefined })\n }\n }, 'tool-web-enhanced-ui: pluginNavigation')\n })\n\n // 1. Composer connection button & menu\n function ComposerButtonSlot(\n props: PropsRuntime<'conversation.input.right'> & PropsLocale<typeof NS>,\n ) {\n const served = useObservable(servedStore)\n const webSnapshot = useObservable(webConfigForm)\n const onOpenPlugins = useObservable(openPluginsStore).open\n const modelKey = props.useProjection('modelSelection', modelKeyOf as (val: unknown) => unknown) as string\n\n return (\n <ComposerConnectionMenu\n sessionId={props.sessionId}\n modelKey={modelKey}\n webConnections={webConnections}\n searchServed={served.searchServed}\n fetchServed={served.fetchServed}\n webConfig={webSnapshot.value}\n onOpenPlugins={onOpenPlugins}\n t={props.t}\n />\n )\n }\n\n ctx.slots.inject('conversation.input.right', () =>\n ctx.slots.register(\n {\n name: 'conversation.input.right',\n id: UI.rowId,\n order: 20,\n locale: NS,\n },\n ComposerButtonSlot,\n ),\n )\n\n // 2. Activation prompt\n function ActivationSlot(props: PluginActivationOwnerProps & PropsLocale<typeof NS>) {\n const served = useObservable(servedStore)\n return <ActivationPrompt {...props} webConfigForm={webConfigForm} nativeSearchServed={served.nativeSearchServed} />\n }\n ctx.slots.inject('plugins.bundle.activation', () =>\n ctx.slots.register(\n {\n name: 'plugins.bundle.activation',\n key: PROFILE_PACKAGE,\n locale: NS,\n },\n ActivationSlot,\n ),\n )\n\n // 3. Profile detail overview section\n function DetailSectionSlot(props: PluginDetailProps & PropsLocale<typeof NS>) {\n const served = useObservable(servedStore)\n\n return (\n <ProfileDetailSection\n subject={props.subject}\n webConfigForm={webConfigForm}\n nativeSearchServed={served.nativeSearchServed}\n webConnections={webConnections}\n t={props.t}\n />\n )\n }\n\n ctx.slots.inject('plugins.detail.section', () =>\n ctx.slots.register(\n {\n name: 'plugins.detail.section',\n id: 'tool-web-enhanced-ui-overview',\n locale: NS,\n },\n DetailSectionSlot,\n ),\n )\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-tool-web-enhanced-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "One composer menu for choosing the search and fetch connections of a DeepSeek Harness session; installed through dsh-tool-web-enhanced-profile",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|