@klarkxy/dsh-web-search-manager 0.3.0 → 0.3.2
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 +14 -14
- package/docs/README.zh-CN.md +13 -13
- package/lib/client.inner.cjs +124 -72
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +124 -72
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -225,6 +225,17 @@ ${scope} {
|
|
|
225
225
|
/* --- Layout scaffolding. --- */
|
|
226
226
|
& .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }
|
|
227
227
|
& .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }
|
|
228
|
+
/* Plugin detail pages share one reading column. These are layout recipes;
|
|
229
|
+
* controls keep their own primitive styles. Form spacing follows the host's
|
|
230
|
+
* settings-form/fields.module.css and SettingsForm.module.css. */
|
|
231
|
+
& .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }
|
|
232
|
+
& .dsh-ui-form { display: flex; flex-direction: column; gap: 0; min-width: 0; }
|
|
233
|
+
&.dsh-ui-form > .dsh-ui-field, & .dsh-ui-form > .dsh-ui-field { padding: 12px 0; }
|
|
234
|
+
& .dsh-ui-form-footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 16px; min-width: 0; }
|
|
235
|
+
& .dsh-ui-fields-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; min-width: 0; margin: 0; padding: 0; border: 0; }
|
|
236
|
+
@media (max-width: 560px) {
|
|
237
|
+
& .dsh-ui-fields-grid { grid-template-columns: minmax(0, 1fr); }
|
|
238
|
+
}
|
|
228
239
|
& .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
229
240
|
& .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
|
|
230
241
|
& .dsh-ui-spacer { flex: 1; min-width: 0; }
|
|
@@ -252,6 +263,9 @@ ${scope} {
|
|
|
252
263
|
* official primitive, so this only owns the vertical rhythm. --- */
|
|
253
264
|
& .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
254
265
|
& .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }
|
|
266
|
+
/* Grid fields share a row, so the stacked-field divider must not win later in
|
|
267
|
+
* the cascade. Reset it here, after the field recipe. */
|
|
268
|
+
& .dsh-ui-fields-grid > .dsh-ui-field { padding: 0; border: 0; }
|
|
255
269
|
& .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }
|
|
256
270
|
& .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
257
271
|
& .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
|
|
@@ -442,9 +456,102 @@ ${scope} {
|
|
|
442
456
|
& *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
|
|
443
457
|
}
|
|
444
458
|
}
|
|
445
|
-
`.replace(/^& (\.dsh-ui-[a-z0-9-]+)(
|
|
459
|
+
`.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?=\s*\{)/gm, (_match, className) => `&${className}, & ${className}`);
|
|
446
460
|
}
|
|
447
461
|
//#endregion
|
|
462
|
+
//#region src/client-styles.ts
|
|
463
|
+
/**
|
|
464
|
+
* The shared contract paints this page: the type tiers, the card, the field,
|
|
465
|
+
* the button row, the notice, the focus ring and the state colours. What is
|
|
466
|
+
* left here is only the geometry the contract does not cover — the reading
|
|
467
|
+
* width of the panel, the ranked three-column row, the drag affordance, the
|
|
468
|
+
* drop indicator, the screen-reader-only announcer and the limits grid.
|
|
469
|
+
*
|
|
470
|
+
* Nothing below declares a colour of its own beyond naming a host token, and
|
|
471
|
+
* nothing carries a literal fallback: the host publishes both themes and a
|
|
472
|
+
* literal would pin one of them.
|
|
473
|
+
*
|
|
474
|
+
* Every plugin rule nests under the plugin root, as the contract does, so a
|
|
475
|
+
* .ws-* or .web-search-* class never paints a neighbouring plugin. Selectors
|
|
476
|
+
* that start with an element name keep an explicit `&`, the form every
|
|
477
|
+
* nesting implementation accepts.
|
|
478
|
+
*/
|
|
479
|
+
const webSearchClientStyles = `${officialUiCss("ws-root")}
|
|
480
|
+
.ws-root {
|
|
481
|
+
|
|
482
|
+
.ws-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 8px; }
|
|
483
|
+
.ws-sr-only {
|
|
484
|
+
position: absolute;
|
|
485
|
+
width: 1px;
|
|
486
|
+
height: 1px;
|
|
487
|
+
padding: 0;
|
|
488
|
+
margin: -1px;
|
|
489
|
+
overflow: hidden;
|
|
490
|
+
clip-path: inset(50%);
|
|
491
|
+
white-space: nowrap;
|
|
492
|
+
border: 0;
|
|
493
|
+
}
|
|
494
|
+
.ws-provider-note { display: flex; align-items: center; gap: 6px; }
|
|
495
|
+
.web-search-provider { display: grid; gap: 8px; min-width: 0; }
|
|
496
|
+
.web-search-provider-info { display: grid; gap: 3px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
|
|
497
|
+
.web-search-provider-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 24px; }
|
|
498
|
+
& a { color: var(--dsw-alias-state-business-primary); font-size: 12px; line-height: 18px; text-underline-offset: 3px; }
|
|
499
|
+
/* The primitive renders a 32px control in an inline-flex wrapper; a settings
|
|
500
|
+
* field needs it to fill the column it sits in. */
|
|
501
|
+
.ws-input { width: 100%; }
|
|
502
|
+
.web-search-rank { margin: 0; padding: 0; list-style: none; }
|
|
503
|
+
.web-search-rank li {
|
|
504
|
+
position: relative;
|
|
505
|
+
display: grid;
|
|
506
|
+
grid-template-columns: 24px minmax(0, 1fr) auto;
|
|
507
|
+
gap: 10px;
|
|
508
|
+
align-items: start;
|
|
509
|
+
padding: 14px 0;
|
|
510
|
+
border-top: 0.5px solid var(--dsw-alias-border-l2);
|
|
511
|
+
}
|
|
512
|
+
& button.web-search-drag-handle {
|
|
513
|
+
display: grid;
|
|
514
|
+
place-items: center;
|
|
515
|
+
width: 24px;
|
|
516
|
+
height: 24px;
|
|
517
|
+
min-height: 24px;
|
|
518
|
+
padding: 0;
|
|
519
|
+
cursor: grab;
|
|
520
|
+
opacity: 0.65;
|
|
521
|
+
}
|
|
522
|
+
& button.web-search-drag-handle:hover { opacity: 1; }
|
|
523
|
+
& button.web-search-drag-handle:active { cursor: grabbing; }
|
|
524
|
+
& button.web-search-drag-handle[aria-disabled='true'] { cursor: wait; opacity: 0.4; }
|
|
525
|
+
.web-search-rank li[data-dragging] { opacity: 0.45; }
|
|
526
|
+
.web-search-rank li[data-drop]::after { content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--dsw-alias-state-business-primary); pointer-events: none; }
|
|
527
|
+
.web-search-rank li[data-drop='before']::after { top: -1px; }
|
|
528
|
+
.web-search-rank li[data-drop='after']::after { bottom: -1px; }
|
|
529
|
+
.web-search-rank-index { color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; line-height: 24px; }
|
|
530
|
+
.web-search-rank-move { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; padding-top: 2px; }
|
|
531
|
+
.ws-danger:hover:not(:disabled),
|
|
532
|
+
.ws-danger[data-armed] { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }
|
|
533
|
+
.ws-danger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }
|
|
534
|
+
@media (max-width: 560px) {
|
|
535
|
+
.web-search-rank-move { flex-direction: column; align-items: flex-end; }
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
`;
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region ../dsh-plugin-kit/src/contracts.ts
|
|
541
|
+
/** `@klarkxy/dsh-git-commit` becomes `KlarkxyDshGitCommitModelSettingsChanges`. */
|
|
542
|
+
function modelSettingsChangesIdentity(packageName) {
|
|
543
|
+
const scoped = /^@([^/]+)\/(.+)$/.exec(packageName);
|
|
544
|
+
const parts = (scoped ? `${scoped[1]}/${scoped[2]}` : packageName).split(/[^A-Za-z0-9]+/).filter(Boolean);
|
|
545
|
+
if (!parts.length) throw new Error("Model settings package name has no RPC segment");
|
|
546
|
+
const segment = `${parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}ModelSettingsChanges`;
|
|
547
|
+
if (!/^[A-Z][A-Za-z0-9]*$/.test(segment)) throw new Error(`Model settings sync name is not an RPC segment: ${segment}`);
|
|
548
|
+
return {
|
|
549
|
+
service: segment,
|
|
550
|
+
namespace: segment
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
modelSettingsChangesIdentity("@klarkxy/dsh-plugin-kit");
|
|
554
|
+
//#endregion
|
|
448
555
|
//#region ../dsh-plugin-kit/src/client-utils.ts
|
|
449
556
|
/** Fixed pause for failing background reads; manual work is never replayed. */
|
|
450
557
|
function createPluginReadGate(now = Date.now) {
|
|
@@ -1292,7 +1399,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1292
1399
|
setNote({ key: "keyDeleted" });
|
|
1293
1400
|
}
|
|
1294
1401
|
if (!status || !limitDraft) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1295
|
-
className: "web-search-settings ws-root dsh-ui-
|
|
1402
|
+
className: "web-search-settings ws-root dsh-ui-page",
|
|
1296
1403
|
children: [loadError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1297
1404
|
role: "alert",
|
|
1298
1405
|
className: "dsh-ui-error",
|
|
@@ -1386,7 +1493,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1386
1493
|
});
|
|
1387
1494
|
}
|
|
1388
1495
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1389
|
-
className: "web-search-settings ws-root dsh-ui-
|
|
1496
|
+
className: "web-search-settings ws-root dsh-ui-page",
|
|
1390
1497
|
"data-testid": "web-search-settings",
|
|
1391
1498
|
children: [
|
|
1392
1499
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
@@ -1747,11 +1854,11 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1747
1854
|
hidden: tab !== "limits",
|
|
1748
1855
|
tabIndex: 0,
|
|
1749
1856
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("fieldset", {
|
|
1750
|
-
className: "
|
|
1857
|
+
className: "dsh-ui-fields-grid",
|
|
1751
1858
|
disabled: busy || reordering,
|
|
1752
1859
|
"aria-label": text.tabLimits,
|
|
1753
1860
|
children: LIMITS.map(([key, min, max]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1754
|
-
className: "
|
|
1861
|
+
className: "dsh-ui-field",
|
|
1755
1862
|
children: [
|
|
1756
1863
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1757
1864
|
className: "dsh-ui-label",
|
|
@@ -1790,7 +1897,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1790
1897
|
})
|
|
1791
1898
|
}),
|
|
1792
1899
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1793
|
-
className: "dsh-ui-
|
|
1900
|
+
className: "dsh-ui-form-footer dsh-ui-actions-end",
|
|
1794
1901
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1795
1902
|
className: "dsh-ui-meta",
|
|
1796
1903
|
children: limitsDirty || keysDirty ? text.unsaved : text.saveHint
|
|
@@ -1805,85 +1912,30 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1805
1912
|
]
|
|
1806
1913
|
});
|
|
1807
1914
|
}
|
|
1808
|
-
const styles = `${officialUiCss("ws-root")}
|
|
1809
|
-
.ws-root { max-width: 760px; }
|
|
1810
|
-
.ws-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 8px; }
|
|
1811
|
-
.ws-sr-only {
|
|
1812
|
-
position: absolute;
|
|
1813
|
-
width: 1px;
|
|
1814
|
-
height: 1px;
|
|
1815
|
-
padding: 0;
|
|
1816
|
-
margin: -1px;
|
|
1817
|
-
overflow: hidden;
|
|
1818
|
-
clip-path: inset(50%);
|
|
1819
|
-
white-space: nowrap;
|
|
1820
|
-
border: 0;
|
|
1821
|
-
}
|
|
1822
|
-
.ws-provider-note { display: flex; align-items: center; gap: 6px; }
|
|
1823
|
-
.web-search-provider { display: grid; gap: 8px; min-width: 0; }
|
|
1824
|
-
.web-search-provider-info { display: grid; gap: 3px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
|
|
1825
|
-
.web-search-provider-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 24px; }
|
|
1826
|
-
.web-search-settings a { color: var(--dsw-alias-state-business-primary); font-size: 12px; line-height: 18px; text-underline-offset: 3px; }
|
|
1827
|
-
/* The primitive renders a 32px control in an inline-flex wrapper; a settings
|
|
1828
|
-
* field needs it to fill the column it sits in. */
|
|
1829
|
-
.ws-input { width: 100%; }
|
|
1830
|
-
.web-search-rank { margin: 0; padding: 0; list-style: none; }
|
|
1831
|
-
.web-search-rank li {
|
|
1832
|
-
position: relative;
|
|
1833
|
-
display: grid;
|
|
1834
|
-
grid-template-columns: 24px minmax(0, 1fr) auto;
|
|
1835
|
-
gap: 10px;
|
|
1836
|
-
align-items: start;
|
|
1837
|
-
padding: 14px 0;
|
|
1838
|
-
border-top: 0.5px solid var(--dsw-alias-border-l2);
|
|
1839
|
-
}
|
|
1840
|
-
.web-search-settings button.web-search-drag-handle {
|
|
1841
|
-
display: grid;
|
|
1842
|
-
place-items: center;
|
|
1843
|
-
width: 24px;
|
|
1844
|
-
height: 24px;
|
|
1845
|
-
min-height: 24px;
|
|
1846
|
-
padding: 0;
|
|
1847
|
-
cursor: grab;
|
|
1848
|
-
opacity: 0.65;
|
|
1849
|
-
}
|
|
1850
|
-
.web-search-settings button.web-search-drag-handle:hover { opacity: 1; }
|
|
1851
|
-
.web-search-settings button.web-search-drag-handle:active { cursor: grabbing; }
|
|
1852
|
-
.web-search-settings button.web-search-drag-handle[aria-disabled='true'] { cursor: wait; opacity: 0.4; }
|
|
1853
|
-
.web-search-rank li[data-dragging] { opacity: 0.45; }
|
|
1854
|
-
.web-search-rank li[data-drop]::after { content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--dsw-alias-state-business-primary); pointer-events: none; }
|
|
1855
|
-
.web-search-rank li[data-drop='before']::after { top: -1px; }
|
|
1856
|
-
.web-search-rank li[data-drop='after']::after { bottom: -1px; }
|
|
1857
|
-
.web-search-rank-index { color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; line-height: 24px; }
|
|
1858
|
-
.web-search-rank-move { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; padding-top: 2px; }
|
|
1859
|
-
.web-search-limits { margin: 0; border: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; }
|
|
1860
|
-
/* A two-column grid, so these fields keep the contract's caption and the
|
|
1861
|
-
* primitive's control and only own their vertical rhythm — a stacked list is
|
|
1862
|
-
* what draws the hairline between fields, and there is nothing to separate. */
|
|
1863
|
-
.ws-limit { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
1864
|
-
.ws-danger:hover:not(:disabled),
|
|
1865
|
-
.ws-danger[data-armed] { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }
|
|
1866
|
-
.ws-danger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }
|
|
1867
|
-
@media (max-width: 560px) { .web-search-rank-move { flex-direction: column; align-items: flex-end; } .web-search-limits { grid-template-columns: minmax(0, 1fr); } }
|
|
1868
|
-
`;
|
|
1869
1915
|
function apply(ctx) {
|
|
1870
1916
|
const client = ctx;
|
|
1871
1917
|
ctx.effect(() => {
|
|
1872
1918
|
if (typeof document === "undefined") return () => {};
|
|
1873
1919
|
const style = document.createElement("style");
|
|
1874
1920
|
style.setAttribute("data-plugin", "@klarkxy/dsh-web-search-manager");
|
|
1875
|
-
style.textContent =
|
|
1921
|
+
style.textContent = webSearchClientStyles;
|
|
1876
1922
|
style.dataset.dshWebSearch = "";
|
|
1877
1923
|
document.head.appendChild(style);
|
|
1878
1924
|
return () => style.remove();
|
|
1879
1925
|
}, "web-search-manager.styles");
|
|
1880
|
-
ctx.effect(() => client.slots.inject("
|
|
1881
|
-
name: "
|
|
1882
|
-
|
|
1926
|
+
ctx.effect(() => client.slots.inject("settings.section", () => [client.slots.register({
|
|
1927
|
+
name: "settings.section",
|
|
1928
|
+
id: "web-search-manager",
|
|
1929
|
+
order: 150,
|
|
1930
|
+
label: () => (client.locale?.getSnapshot().active ?? "zh").startsWith("zh") ? "网页搜索" : "Web Search"
|
|
1883
1931
|
}, (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkSearchSettings, {
|
|
1884
1932
|
client,
|
|
1885
1933
|
hidden: props?.hidden
|
|
1886
|
-
}))
|
|
1934
|
+
})), client.slots.inject("settings.section.icon", () => client.slots.register({
|
|
1935
|
+
name: "settings.section.icon",
|
|
1936
|
+
id: "web-search-manager",
|
|
1937
|
+
order: 150
|
|
1938
|
+
}, _deepseek_ai_dsh_client_ui_primitives.IconGlobeOutlineRegular))]), "web-search-manager.settings");
|
|
1887
1939
|
}
|
|
1888
1940
|
//#endregion
|
|
1889
1941
|
exports.NetworkSearchSettings = NetworkSearchSettings;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klarkxy/dsh-web-search-manager",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Manage and rank search and page-reading services, including providers from installed plugins, in one settings page.",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"@deepseek-ai/dsh-web-search-exa": ">=0.2.0-rc.2",
|
|
83
|
-
"@klarkxy/dsh-plugin-kit": "0.
|
|
83
|
+
"@klarkxy/dsh-plugin-kit": "0.6.0",
|
|
84
84
|
"zod": "^4.1.5"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
@@ -152,6 +152,6 @@
|
|
|
152
152
|
"registry": "https://registry.npmjs.org/"
|
|
153
153
|
},
|
|
154
154
|
"dshRelease": {
|
|
155
|
-
"contentHash": "
|
|
155
|
+
"contentHash": "10f7882d994668e9a3c65af01077247fb3ee0b34e6fef5ca70c7b5ba2157eaef"
|
|
156
156
|
}
|
|
157
157
|
}
|