@klarkxy/dsh-zhihu 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,17 +2,23 @@
2
2
 
3
3
  Zhihu search, answers, knowledge bases, and usage tracking for DSH.
4
4
 
5
- [简体中文](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/docs/README.zh-CN.md)
5
+ [简体中文](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/docs/README.zh-CN.md)
6
6
 
7
7
  ## Install
8
8
 
9
- Requires Node.js ≥22 and DSH `0.1.7-rc.2`. No repository build is needed.
9
+ Requires Node.js ≥22 and DSH `0.1.7-rc.2`. No repository build is needed. Install:
10
+
11
+ ```sh
12
+ npm install @klarkxy/dsh-zhihu
13
+ ```
14
+
15
+ Then load it:
10
16
 
11
17
  ```sh
12
18
  dsh plugin --profile web add @klarkxy/dsh-zhihu
13
19
  ```
14
20
 
15
- Restart DSH Web, open **Zhihu resources**, and enter your Access Secret (DSH credential `ZHIHU_ACCESS_TOKEN`). Use the full scoped name; the unscoped `dsh-zhihu` package belongs to another maintainer.
21
+ Restart DSH Web, open **Plugins → @klarkxy/dsh-zhihu**, and enter your Access Secret (DSH credential `ZHIHU_ACCESS_TOKEN`). Use the full scoped name; the unscoped `dsh-zhihu` package belongs to another maintainer.
16
22
 
17
23
  To enable agent tools, add this entry to the plugin list in the agent's `agent.cordis.yml`:
18
24
 
@@ -22,14 +28,26 @@ To enable agent tools, add this entry to the plugin list in the agent's `agent.c
22
28
 
23
29
  ## Use
24
30
 
25
- DSH Web provides search, settings, usage, and knowledge-base views. In DSH Editor, open **Settings → Zhihu resources** for configuration, usage, knowledge bases, and a connection test; the agent tools are included.
31
+ DSH Web provides search, settings, usage, and knowledge-base views. Open **Plugins → @klarkxy/dsh-zhihu** for configuration, usage, knowledge bases, and search; the agent tools are included.
26
32
 
27
- Search covers Zhihu, the wider web, trending topics, answers, and public knowledge bases. Uploaded reference files are stored in Zhihu's cloud; do not upload unpublished manuscripts.
33
+ Five agent tools are available once the tools entry is enabled:
34
+
35
+ - `zhihu_search`: search within Zhihu for community evidence; results are community/reader feedback only, never canon, and never written into project files.
36
+ - `zhihu_global_search`: search the wider web beyond Zhihu through the open platform's global search; reference only.
37
+ - `zhihu_hot_list`: pull the Zhihu hot list to see current community trends; reference for topics and hotspots only.
38
+ - `zhihu_ask`: ask Zhihu 直答, an OpenAI-compatible AI answer service grounded in Zhihu community content; suited for research and background investigation.
39
+ - `zhihu_knowledge_search`: retrieve RAG fragments from Zhihu knowledge bases — public bases by default, with personal and subscription recall scopes available after you upload material on Zhihu's web side.
40
+
41
+ Usage is tracked as daily counters of calls, failures, and returned results; usage views default to the last 30 days and accept at most 90. Knowledge-base uploads are limited to 20 MB per file.
42
+
43
+ Search covers Zhihu in-site search, the wider web, the hot list, Zhihu 直答 AI answers, and public knowledge bases. Uploaded reference files are stored in Zhihu's cloud; do not upload unpublished manuscripts.
28
44
 
29
45
  When [@klarkxy/dsh-web-search-manager](https://www.npmjs.com/package/@klarkxy/dsh-web-search-manager) is also installed in the same profile, this plugin registers **Zhihu global search** as a provider in its web search settings. Enable that provider to use Zhihu's global search through the standard web search tool with the Access Secret from Zhihu settings. The dedicated Zhihu tools work independently.
30
46
 
31
47
  ## Development
32
48
 
33
- Read [contracts](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/src/contracts.ts) and [tools](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/src/tools.ts) for the API.
49
+ Read [contracts](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/src/contracts.ts) and [tools](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/src/tools.ts) for the API.
50
+
51
+ [Publishing](https://github.com/klarkxy/dsh-plugins/blob/main/docs/editor-plugin-migration.md) · [License](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/LICENSE)
34
52
 
35
- [Publishing](https://github.com/klarkxy/dsh-editor/blob/main/packages/PUBLISHING.md) · [License](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/LICENSE)
53
+ The client accepts structural host controls and has native HTML fallbacks. Building or using this package does not require application-private UI packages. Agent tools, credentials, RPC contracts and storage identifiers are unchanged.
@@ -2,17 +2,23 @@
2
2
 
3
3
  DSH 知乎搜索、直答、知识库与用量插件。
4
4
 
5
- [English](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/README.md)
5
+ [English](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/README.md)
6
6
 
7
7
  ## 安装
8
8
 
9
- 需要 Node.js ≥22、DSH `0.1.7-rc.2`,无需构建本仓库。
9
+ 需要 Node.js ≥22、DSH `0.1.7-rc.2`,无需构建本仓库。安装:
10
+
11
+ ```sh
12
+ npm install @klarkxy/dsh-zhihu
13
+ ```
14
+
15
+ 然后加载:
10
16
 
11
17
  ```sh
12
18
  dsh plugin --profile web add @klarkxy/dsh-zhihu
13
19
  ```
14
20
 
15
- 重启 DSH Web,打开「知乎资料」填写 Access Secret(DSH 凭据 `ZHIHU_ACCESS_TOKEN`)。请使用完整 scoped 包名;无 scope 的 `dsh-zhihu` 属于其他维护者。
21
+ 重启 DSH Web,从「插件」打开「知乎(@klarkxy/dsh-zhihu)」填写 Access Secret(DSH 凭据 `ZHIHU_ACCESS_TOKEN`)。请使用完整 scoped 包名;无 scope 的 `dsh-zhihu` 属于其他维护者。
16
22
 
17
23
  模型需要使用知乎工具时,在所用 `agent.cordis.yml` 的插件列表加入:
18
24
 
@@ -22,7 +28,17 @@ dsh plugin --profile web add @klarkxy/dsh-zhihu
22
28
 
23
29
  ## 使用
24
30
 
25
- DSH Web 提供搜索、设置、用量与知识库视图。DSH Editor 在「设置 → 知乎资料」配置、查看用量、管理知识库和测试连接,已内置模型工具。
31
+ DSH Web 提供搜索、设置、用量与知识库视图。在「插件 → 知乎(@klarkxy/dsh-zhihu)」配置、查看用量、管理知识库和搜索;模型工具随插件一同提供。
32
+
33
+ 启用 tools 入口后,模型可使用五个工具:
34
+
35
+ - `zhihu_search`:知乎站内搜索,拉取社区证据;结果仅作社区/读者反馈参考,不构成 canon,也不直接写入项目文件。
36
+ - `zhihu_global_search`:知乎开放平台全网搜索,检索站外公开网页资料;仅作参考。
37
+ - `zhihu_hot_list`:拉取知乎热榜,了解当前社区热点;仅作题材与热点参考。
38
+ - `zhihu_ask`:调用知乎直答(OpenAI 兼容的 AI 问答),基于知乎社区内容生成综合回答;适合考据与背景调研。
39
+ - `zhihu_knowledge_search`:检索知乎知识库(RAG 片段),默认只查公开库;在知乎网页端上传过个人资料后可加个人/订阅召回范围。
40
+
41
+ 用量按日计数(调用次数、失败次数与成功调用返回的条目数),视图默认展示最近 30 天,最多可查 90 天。知识库上传单文件上限 20 MB。
26
42
 
27
43
  可查询站内、全网、热榜、直答和公开知识库。上传的参考文件保存在知乎云端,请勿上传未发表手稿。
28
44
 
@@ -30,6 +46,8 @@ DSH Web 提供搜索、设置、用量与知识库视图。DSH Editor 在「设
30
46
 
31
47
  ## 开发
32
48
 
33
- 接口见 [contracts](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/src/contracts.ts) 与 [tools](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/src/tools.ts)。
49
+ 接口见 [contracts](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/src/contracts.ts) 与 [tools](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/src/tools.ts)。
50
+
51
+ [发布维护](https://github.com/klarkxy/dsh-plugins/blob/main/docs/editor-plugin-migration.md) · [许可证](https://github.com/klarkxy/dsh-plugins/blob/main/plugins/dsh-zhihu/LICENSE)
34
52
 
35
- [发布维护](https://github.com/klarkxy/dsh-editor/blob/main/packages/PUBLISHING.md) · [许可证](https://github.com/klarkxy/dsh-editor/blob/main/packages/dsh-zhihu/LICENSE)
53
+ 客户端接收宿主提供的结构化控件,缺失时使用原生 HTML 控件。构建和使用本包不依赖应用私有 UI 包;Agent 工具、凭据、RPC 合同和存储标识保持不变。
package/icon.svg ADDED
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36" fill="none">
2
+ <defs>
3
+ <linearGradient id="zbubble" x1="6" y1="6" x2="30" y2="28" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#4D75F5"/>
5
+ <stop offset="1" stop-color="#8EB6FF"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <g transform="translate(3.6 3.6) scale(.8)">
9
+ <path d="M6 9C6 7.3 7.3 6 9 6H27C28.7 6 30 7.3 30 9V21C30 22.7 28.7 24 27 24H20L13 30V24H9C7.3 24 6 22.7 6 21V9Z" fill="url(#zbubble)"/>
10
+ <path d="M11 12H25M11 12V19M25 12V19M11 19H25M18 12V19" stroke="#E0EBFF" stroke-width="2" stroke-linecap="round"/>
11
+ <circle cx="14.5" cy="15.5" r="1.4" fill="#65DED0"/>
12
+ <circle cx="21.5" cy="15.5" r="1.4" fill="#65DED0"/>
13
+ </g>
14
+ </svg>
package/lib/client.js CHANGED
@@ -216,18 +216,15 @@ function createZhihuClientState() {
216
216
  //#region src/client-styles.ts
217
217
  const standaloneOutsideTheme = ":not(.radix-themes *)";
218
218
  const zhihuClientStyles = `
219
- .zhihu-dock {
220
- position: var(--dsh-ext-dock-position, absolute);
221
- right: var(--dsh-ext-dock-right, var(--space-4, 16px));
222
- bottom: var(--dsh-ext-dock-bottom, calc(var(--space-4, 16px) + 44px));
223
- pointer-events: auto;
224
- }
219
+
225
220
  .zhihu-settings-embed {
226
221
  font: 400 var(--font-size-2)/1.5 var(--default-font-family);
227
222
  color: var(--gray-12);
228
223
  display: flex;
229
224
  flex-direction: column;
230
225
  min-width: 0;
226
+ width: 100%;
227
+ max-width: 760px;
231
228
  min-height: 0;
232
229
  gap: 0;
233
230
  }
@@ -238,73 +235,19 @@ const zhihuClientStyles = `
238
235
  padding: var(--space-4) 0 0;
239
236
  overflow: visible;
240
237
  }
241
- .zhihu-toggle {
242
- pointer-events: auto;
243
- font: inherit;
244
- font-family: var(--default-font-family);
245
- font-size: var(--font-size-2);
246
- min-height: var(--control-h, 34px);
247
- color: var(--gray-11);
248
- background: var(--color-panel-solid);
249
- border: 1px solid var(--gray-6);
250
- border-radius: 999px;
251
- padding: 0 14px;
252
- cursor: pointer;
253
- box-shadow: var(--shadow-3);
254
- }
255
- .zhihu-toggle:hover { border-color: var(--accent-9); color: var(--accent-11); background: var(--gray-a3); }
256
- .zhihu-toggle:focus-visible,
257
238
  .zhihu-panel button:focus-visible,
258
239
  .zhihu-panel input:focus-visible,
259
240
  .zhihu-panel select:focus-visible,
260
241
  .zhihu-panel a:focus-visible {
261
242
  box-shadow: 0 0 0 2px var(--accent-a8);
262
243
  }
263
- .zhihu-dock .zhihu-panel {
264
- position: absolute;
265
- top: var(--dsh-ext-panel-top, auto);
266
- right: 0;
267
- bottom: var(--dsh-ext-panel-bottom, calc(100% + 6px));
268
- z-index: 10;
269
- width: min(440px, calc(100vw - 32px));
270
- max-height: min(72vh, 620px);
271
- display: flex;
272
- flex-direction: column;
273
- pointer-events: auto;
274
- font-family: var(--default-font-family);
275
- font-size: var(--font-size-2);
276
- color: var(--gray-12);
277
- background: var(--color-panel-solid);
278
- border: 1px solid var(--gray-6);
279
- border-radius: var(--radius-3);
280
- box-shadow: var(--shadow-4);
281
- overflow: hidden;
282
- }
244
+
283
245
  .zhihu-panel {
284
246
  font-family: var(--default-font-family);
285
247
  font-size: var(--font-size-2);
286
248
  color: var(--gray-12);
287
249
  background: var(--color-panel-solid);
288
250
  }
289
- .zhihu-panel-header {
290
- display: flex;
291
- align-items: center;
292
- justify-content: space-between;
293
- padding: var(--space-2) var(--space-3);
294
- border-bottom: 1px solid var(--gray-6);
295
- }
296
- .zhihu-panel-title {
297
- margin: 0;
298
- font-size: var(--font-size-2);
299
- font-weight: var(--font-weight-medium);
300
- font-family: var(--default-font-family);
301
- }
302
- .zhihu-panel-close {
303
- font: inherit; font-size: var(--font-size-2); min-height: 32px; color: var(--gray-11); background: none; border: none;
304
- border-radius: var(--radius-2); padding: 0 8px; cursor: pointer;
305
- }
306
- .zhihu-panel-close:hover { color: var(--gray-12); background: var(--gray-a3); }
307
- .zhihu-panel-close:disabled { opacity: 0.5; cursor: default; }
308
251
  .zhihu-tabs {
309
252
  display: inline-flex;
310
253
  gap: 2px;
@@ -500,17 +443,13 @@ const zhihuClientStyles = `
500
443
  .zhihu-dots i:nth-child(2) { animation-delay: .2s; }
501
444
  .zhihu-dots i:nth-child(3) { animation-delay: .4s; }
502
445
  @media (prefers-reduced-motion: reduce) {
503
- .zhihu-dock, .zhihu-dock *, .zhihu-panel, .zhihu-panel * {
446
+ .zhihu-panel, .zhihu-panel * {
504
447
  animation: none !important; transition: none !important;
505
448
  transform: none !important; filter: none !important;
506
449
  }
507
450
  .zhihu-dots i { animation: none; }
508
451
  }
509
- /* Local tokens when this overlay is not under .radix-themes. Host Theme
510
- and --dsh-ext-* rail overrides still win inside the Theme tree. Dark
511
- follows body[data-ds-dark-theme] / :root[data-theme=dark], not OS scheme. */
512
- .zhihu-dock${standaloneOutsideTheme},
513
- .zhihu-toggle${standaloneOutsideTheme},
452
+ /* Local tokens follow the host theme when the settings page is outside Radix. */
514
453
  .zhihu-panel${standaloneOutsideTheme} {
515
454
 
516
455
  --default-font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei UI", system-ui, sans-serif;
@@ -572,11 +511,7 @@ const zhihuClientStyles = `
572
511
  --shadow-4: 0 0 0 1px #0000000f, 0 8px 40px rgba(0, 0, 0, 0.05), 0 12px 32px -16px #0000000f;
573
512
  color-scheme: light;
574
513
  }
575
- html:not([data-theme]) body[data-ds-dark-theme] .zhihu-dock${standaloneOutsideTheme},
576
- html:not([data-theme]) body[data-ds-dark-theme] .zhihu-toggle${standaloneOutsideTheme},
577
514
  html:not([data-theme]) body[data-ds-dark-theme] .zhihu-panel${standaloneOutsideTheme},
578
- :root[data-theme="dark"] .zhihu-dock${standaloneOutsideTheme},
579
- :root[data-theme="dark"] .zhihu-toggle${standaloneOutsideTheme},
580
515
  :root[data-theme="dark"] .zhihu-panel${standaloneOutsideTheme} {
581
516
 
582
517
  --default-font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei UI", system-ui, sans-serif;
@@ -661,12 +596,6 @@ function zhihuQueryKeyDown(event, run) {
661
596
  run.search();
662
597
  }
663
598
  }
664
- function dockEscapeKeyDown(event, run) {
665
- if (event.key !== "Escape") return;
666
- event.stopPropagation();
667
- if (run.loading) return;
668
- run.close();
669
- }
670
599
  function hostComponentsFromRenderProps(props) {
671
600
  if (!props || typeof props !== "object") return {};
672
601
  const record = props;
@@ -711,10 +640,8 @@ function renderSelect(Select, props, className) {
711
640
  }, option.value === "" ? "__empty" : option.value))
712
641
  });
713
642
  }
714
- //#endregion
715
- //#region ../dsh-editor-seats/src/seat-button.tsx
716
- const SeatButton = (0, react.forwardRef)(function SeatButton(props, ref) {
717
- const { host, variant, className, ...rest } = props;
643
+ /** Prefer a structurally supplied host control; standalone Web needs no private UI package. */
644
+ const ZhihuButton = (0, react.forwardRef)(function ZhihuButton({ host, variant, className, ...rest }, ref) {
718
645
  if (host) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(host, {
719
646
  ref,
720
647
  variant,
@@ -737,9 +664,9 @@ const inject = [
737
664
  "remote",
738
665
  "remote.credentials"
739
666
  ];
740
- const SLOT_ID = "zhihu";
667
+ const PACKAGE_NAME = "@klarkxy/dsh-zhihu";
741
668
  const SLOT_ORDER = 120;
742
- const SLOT_LABEL = "知乎资料";
669
+ const SLOT_LABEL = "知乎";
743
670
  const activityDots = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
744
671
  className: "zhihu-dots",
745
672
  "aria-hidden": "true",
@@ -1101,7 +1028,7 @@ function SettingsSection(props) {
1101
1028
  if (state.status === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsShell, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1102
1029
  className: "zhihu-error",
1103
1030
  role: "alert",
1104
- children: [`读取失败:${state.error} `, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1031
+ children: [`读取失败:${state.error} `, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1105
1032
  host: props.Button,
1106
1033
  className: "zhihu-button",
1107
1034
  onClick: () => void load(),
@@ -1227,14 +1154,14 @@ function SettingsSection(props) {
1227
1154
  }) : null,
1228
1155
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1229
1156
  className: "zhihu-row",
1230
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1157
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1231
1158
  host: props.Button,
1232
1159
  variant: "danger",
1233
1160
  className: "zhihu-button zhihu-button-danger",
1234
1161
  disabled: busy || keyLocked || !configured,
1235
1162
  onClick: () => void clear(),
1236
1163
  children: busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [activityDots(), "处理中…"] }) : "清除"
1237
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1164
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1238
1165
  host: props.Button,
1239
1166
  variant: "primary",
1240
1167
  className: "zhihu-button zhihu-button-primary",
@@ -1480,7 +1407,7 @@ function UsageSection(props) {
1480
1407
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1481
1408
  className: "zhihu-error",
1482
1409
  role: "alert",
1483
- children: [`读取失败:${state.error} `, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1410
+ children: [`读取失败:${state.error} `, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1484
1411
  host: props.Button,
1485
1412
  className: "zhihu-button",
1486
1413
  onClick: () => void load(),
@@ -1737,7 +1664,7 @@ function KnowledgeSection(props) {
1737
1664
  list.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1738
1665
  className: "zhihu-error",
1739
1666
  role: "alert",
1740
- children: [`${list.failure.text} `, list.failure.kind !== "credential" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1667
+ children: [`${list.failure.text} `, list.failure.kind !== "credential" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1741
1668
  host: props.Button,
1742
1669
  className: "zhihu-button",
1743
1670
  onClick: () => void load(),
@@ -1766,7 +1693,7 @@ function KnowledgeSection(props) {
1766
1693
  value: base.id,
1767
1694
  label: `${base.name}${base.isDefault ? "(默认)" : ""} · ${base.contentCount} 篇`
1768
1695
  }))]
1769
- }, "zhihu-select"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1696
+ }, "zhihu-select"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1770
1697
  host: props.Button,
1771
1698
  className: "zhihu-button",
1772
1699
  disabled: busy,
@@ -1797,7 +1724,7 @@ function KnowledgeSection(props) {
1797
1724
  disabled: busy,
1798
1725
  onChange: (event) => setFile(event.target.files?.[0])
1799
1726
  }, fileKey),
1800
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1727
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1801
1728
  host: props.Button,
1802
1729
  className: "zhihu-button",
1803
1730
  disabled: busy,
@@ -1812,7 +1739,7 @@ function KnowledgeSection(props) {
1812
1739
  }) : null,
1813
1740
  list.status === "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1814
1741
  className: "zhihu-row",
1815
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1742
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1816
1743
  host: props.Button,
1817
1744
  variant: "primary",
1818
1745
  className: "zhihu-button zhihu-button-primary",
@@ -1840,31 +1767,18 @@ const TAB_LABEL = {
1840
1767
  usage: "用量",
1841
1768
  knowledge: "知识库"
1842
1769
  };
1843
- const OVERLAY_TABS = [
1844
- "search",
1845
- "settings",
1846
- "usage",
1847
- "knowledge"
1848
- ];
1849
1770
  const SETTINGS_TABS = [
1850
1771
  "settings",
1851
1772
  "usage",
1852
1773
  "knowledge",
1853
1774
  "search"
1854
1775
  ];
1855
- function tabLabel(tab, surface) {
1856
- if (tab === "search" && surface === "settings") return "连接测试";
1857
- return TAB_LABEL[tab];
1858
- }
1859
- function ZhihuDock(props) {
1860
- const { rpc, credentials, Select, Dialog, Button, Input } = props;
1861
- const surface = props.surface === "settings" ? "settings" : "overlay";
1862
- const tabs = surface === "settings" ? SETTINGS_TABS : OVERLAY_TABS;
1776
+ function ZhihuSettings(props) {
1777
+ const { rpc, credentials, Select, Button, Input } = props;
1863
1778
  const gateRef = (0, react.useRef)(null);
1864
1779
  if (!gateRef.current) gateRef.current = createZhihuClientState();
1865
1780
  const gate = gateRef.current;
1866
- const [open, setOpen] = (0, react.useState)(surface === "settings");
1867
- const [tab, setTab] = (0, react.useState)(surface === "settings" ? "settings" : "search");
1781
+ const [tab, setTab] = (0, react.useState)("settings");
1868
1782
  const [query, setQuery] = (0, react.useState)("");
1869
1783
  const [mode, setMode] = (0, react.useState)("search");
1870
1784
  const [askModel, setAskModel] = (0, react.useState)("zhida-thinking-1p5");
@@ -1874,23 +1788,7 @@ function ZhihuDock(props) {
1874
1788
  const [outcome, setOutcome] = (0, react.useState)(null);
1875
1789
  const [revision, setRevision] = (0, react.useState)(0);
1876
1790
  const [resultRevision, setResultRevision] = (0, react.useState)(0);
1877
- const toggleRef = (0, react.useRef)(null);
1878
1791
  const queryRef = (0, react.useRef)(null);
1879
- const wasOpen = (0, react.useRef)(false);
1880
- (0, react.useEffect)(() => {
1881
- if (Dialog || surface === "settings") return;
1882
- if (open) {
1883
- wasOpen.current = true;
1884
- queryRef.current?.focus();
1885
- } else if (wasOpen.current) {
1886
- wasOpen.current = false;
1887
- toggleRef.current?.focus();
1888
- }
1889
- }, [
1890
- open,
1891
- Dialog,
1892
- surface
1893
- ]);
1894
1792
  (0, react.useEffect)(() => () => gate.cancel(), [gate]);
1895
1793
  const runSearch = (0, react.useCallback)(async () => {
1896
1794
  if (mode !== "hot" && !query.trim()) return;
@@ -1980,17 +1878,6 @@ function ZhihuDock(props) {
1980
1878
  setAskModel(next);
1981
1879
  resetToIdle();
1982
1880
  };
1983
- const closePanel = (0, react.useCallback)(() => {
1984
- gate.cancel();
1985
- setPhase("idle");
1986
- setOpen(false);
1987
- }, [gate]);
1988
- const onPanelKeyDown = (event) => {
1989
- dockEscapeKeyDown(event, {
1990
- loading: phase === "loading",
1991
- close: closePanel
1992
- });
1993
- };
1994
1881
  const onQueryKeyDown = (event) => {
1995
1882
  zhihuQueryKeyDown(event, {
1996
1883
  disabled: isSearchDisabled(),
@@ -2021,7 +1908,7 @@ function ZhihuDock(props) {
2021
1908
  buttons[next]?.focus();
2022
1909
  buttons[next]?.click();
2023
1910
  },
2024
- children: tabs.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1911
+ children: SETTINGS_TABS.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2025
1912
  host: Button,
2026
1913
  type: "button",
2027
1914
  role: "tab",
@@ -2029,7 +1916,7 @@ function ZhihuDock(props) {
2029
1916
  tabIndex: tab === key ? 0 : -1,
2030
1917
  className: "zhihu-tab",
2031
1918
  onClick: () => onTabChange(key),
2032
- children: tabLabel(key, surface)
1919
+ children: TAB_LABEL[key]
2033
1920
  }, key))
2034
1921
  }, "tabs");
2035
1922
  const body = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -2063,7 +1950,7 @@ function ZhihuDock(props) {
2063
1950
  className: "zhihu-scopes",
2064
1951
  role: "group",
2065
1952
  "aria-label": "检索范围",
2066
- children: SCOPE_OPTIONS.map((scope) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1953
+ children: SCOPE_OPTIONS.map((scope) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2067
1954
  host: Button,
2068
1955
  role: "checkbox",
2069
1956
  "aria-checked": scopes.includes(scope.value),
@@ -2086,7 +1973,7 @@ function ZhihuDock(props) {
2086
1973
  }),
2087
1974
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2088
1975
  className: "zhihu-row",
2089
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1976
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2090
1977
  host: Button,
2091
1978
  variant: "primary",
2092
1979
  className: "zhihu-button zhihu-button-primary",
@@ -2094,7 +1981,7 @@ function ZhihuDock(props) {
2094
1981
  disabled: searchDisabled,
2095
1982
  onClick: () => void runSearch(),
2096
1983
  children: phase === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [activityDots(), "请求中…"] }) : mode === "hot" ? "获取热榜" : "搜索"
2097
- }), phase === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
1984
+ }), phase === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2098
1985
  host: Button,
2099
1986
  className: "zhihu-button",
2100
1987
  onClick: () => {
@@ -2104,7 +1991,7 @@ function ZhihuDock(props) {
2104
1991
  children: "取消"
2105
1992
  }) : null]
2106
1993
  }),
2107
- surface !== "settings" && phase === "idle" && mode !== "hot" && !query.trim() ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1994
+ phase === "idle" && mode !== "hot" && !query.trim() ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2108
1995
  className: "zhihu-status",
2109
1996
  role: "status",
2110
1997
  children: "输入关键词后搜索。"
@@ -2141,62 +2028,12 @@ function ZhihuDock(props) {
2141
2028
  }) : null
2142
2029
  ]
2143
2030
  }, "body");
2144
- const inner = [
2145
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
2146
- className: "zhihu-panel-header",
2147
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
2148
- className: "zhihu-panel-title",
2149
- children: "知乎资料"
2150
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
2151
- host: Button,
2152
- className: "zhihu-panel-close",
2153
- disabled: phase === "loading",
2154
- onClick: closePanel,
2155
- children: "关闭"
2156
- })]
2157
- }, "header"),
2158
- tablist,
2159
- body
2160
- ];
2161
- if (surface === "settings") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2162
- className: "zhihu-settings-embed",
2031
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2032
+ className: "zhihu-panel zhihu-settings-embed",
2163
2033
  "data-testid": "zhihu-settings-embed",
2164
2034
  "aria-label": SLOT_LABEL,
2165
2035
  children: [tablist, body]
2166
2036
  });
2167
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2168
- className: "zhihu-dock",
2169
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SeatButton, {
2170
- host: Button,
2171
- ref: toggleRef,
2172
- className: "zhihu-toggle",
2173
- "data-testid": "zhihu-open",
2174
- onClick: () => setOpen(true),
2175
- children: SLOT_LABEL
2176
- }), Dialog ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dialog, {
2177
- open,
2178
- onOpenChange: (next) => {
2179
- if (!next) closePanel();
2180
- else setOpen(true);
2181
- },
2182
- title: "知乎资料",
2183
- className: "file-dialog zhihu-panel",
2184
- overlayClassName: "file-dialog-overlay",
2185
- dismissible: phase !== "loading",
2186
- initialFocusRef: queryRef,
2187
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2188
- "data-testid": "zhihu-panel",
2189
- className: "zhihu-panel-inner",
2190
- children: inner
2191
- })
2192
- }) : open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
2193
- className: "zhihu-panel",
2194
- "data-testid": "zhihu-panel",
2195
- "aria-label": "知乎资料",
2196
- onKeyDown: onPanelKeyDown,
2197
- children: inner
2198
- }) : null]
2199
- });
2200
2037
  }
2201
2038
  function apply(ctx) {
2202
2039
  ctx.effect(() => {
@@ -2204,33 +2041,17 @@ function apply(ctx) {
2204
2041
  return () => style?.remove();
2205
2042
  }, "zhihu.styles");
2206
2043
  const client = ctx;
2207
- const overlayRender = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuDock, {
2044
+ const settingsRender = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuSettings, {
2208
2045
  rpc: client.connection.rpc,
2209
2046
  credentials: wrapCredentials(client.remote.credentials),
2210
- surface: "overlay",
2211
2047
  ...hostComponentsFromRenderProps(props)
2212
2048
  });
2213
- const settingsRender = (props) => {
2214
- const host = hostComponentsFromRenderProps(props);
2215
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuDock, {
2216
- rpc: client.connection.rpc,
2217
- credentials: wrapCredentials(client.remote.credentials),
2218
- surface: "settings",
2219
- ...host
2220
- });
2221
- };
2222
- client.slots.inject("shell.overlay", () => client.slots.register({
2223
- name: "shell.overlay",
2224
- id: SLOT_ID,
2225
- order: SLOT_ORDER,
2226
- label: SLOT_LABEL
2227
- }, overlayRender));
2228
- client.slots.inject("dsh-editor.settings.zhihu", () => client.slots.register({
2229
- name: "dsh-editor.settings.zhihu",
2230
- id: SLOT_ID,
2049
+ ctx.effect(() => client.slots.inject("plugins.bundle.config", () => client.slots.register({
2050
+ name: "plugins.bundle.config",
2051
+ key: PACKAGE_NAME,
2231
2052
  order: SLOT_ORDER,
2232
2053
  label: SLOT_LABEL
2233
- }, settingsRender));
2054
+ }, settingsRender)), "zhihu.settings");
2234
2055
  }
2235
2056
  //#endregion
2236
2057
  exports.apply = apply;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klarkxy/dsh-zhihu",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Zhihu search, agent tools, knowledge bases, and usage tracking for DeepSeek Harness.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -36,6 +36,7 @@
36
36
  "./package.json": "./package.json"
37
37
  },
38
38
  "files": [
39
+ "icon.svg",
39
40
  "lib/*.js",
40
41
  "lib/*.js.map",
41
42
  "lib/*.d.ts",
@@ -63,7 +64,7 @@
63
64
  "entries": [
64
65
  {
65
66
  "id": "zhihu",
66
- "title": "知乎资料",
67
+ "title": "知乎",
67
68
  "description": "知乎搜索、知识库与用量",
68
69
  "feature": "zhihu",
69
70
  "service": "zhihu"
@@ -82,24 +83,37 @@
82
83
  }
83
84
  ]
84
85
  },
86
+ "scripts": {
87
+ "build": "tsdown && node ../../scripts/editor-plugins/wrap-client.mjs @klarkxy/dsh-zhihu",
88
+ "typecheck": "tsc --noEmit -p tsconfig.json",
89
+ "test": "vitest run --root ../.. --config vitest.editor-plugins.config.ts --maxWorkers=2 plugins/dsh-zhihu/src"
90
+ },
85
91
  "dependencies": {
86
- "@deepseek-ai/dsh-storage-domain": "0.1.7-rc.2",
87
92
  "zod": "^4.1.5"
88
93
  },
89
94
  "peerDependencies": {
90
95
  "@deepseek-ai/cordis": "^4.0.4",
91
- "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
92
- "@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1 <0.2.0"
96
+ "@deepseek-ai/dsh-credentials": ">=0.1.7-rc.2",
97
+ "@deepseek-ai/dsh-storage-domain": ">=0.1.7-rc.2",
98
+ "@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1"
93
99
  },
94
100
  "devDependencies": {
95
101
  "@deepseek-ai/cordis": "^4.0.4",
96
102
  "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
103
+ "@deepseek-ai/dsh-storage-domain": "0.1.7-rc.2",
97
104
  "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
98
105
  "react": "^18.2.0",
99
106
  "@types/react": "18.3.31",
100
- "dsh-editor-seats": "0.1.0"
107
+ "react-dom": "^18.2.0",
108
+ "@types/react-dom": "^18.3.1"
101
109
  },
102
110
  "peerDependenciesMeta": {
111
+ "@deepseek-ai/dsh-credentials": {
112
+ "optional": true
113
+ },
114
+ "@deepseek-ai/dsh-storage-domain": {
115
+ "optional": true
116
+ },
103
117
  "@deepseek-ai/dsh-tools": {
104
118
  "optional": true
105
119
  }
@@ -116,23 +130,18 @@
116
130
  ],
117
131
  "repository": {
118
132
  "type": "git",
119
- "url": "git+https://github.com/klarkxy/dsh-editor.git",
120
- "directory": "packages/dsh-zhihu"
133
+ "url": "git+https://github.com/klarkxy/dsh-plugins.git",
134
+ "directory": "plugins/dsh-zhihu"
121
135
  },
122
- "homepage": "https://github.com/klarkxy/dsh-editor/tree/main/packages/dsh-zhihu#readme",
136
+ "homepage": "https://klarkxy.github.io/dsh-plugins/plugins/zhihu/",
123
137
  "bugs": {
124
- "url": "https://github.com/klarkxy/dsh-editor/issues"
138
+ "url": "https://github.com/klarkxy/dsh-plugins/issues"
125
139
  },
126
140
  "publishConfig": {
127
141
  "access": "public",
128
142
  "registry": "https://registry.npmjs.org/"
129
143
  },
130
144
  "dshRelease": {
131
- "contentHash": "sha256-09f8c9b11a25529dc222920deb2eb6b236d948a9dec4d280efc17177b1fd9e23"
132
- },
133
- "scripts": {
134
- "build": "tsdown && node ../../scripts/wrap-client.mjs @klarkxy/dsh-zhihu",
135
- "typecheck": "tsc --noEmit -p tsconfig.json",
136
- "test": "vitest run --root ../.. packages/dsh-zhihu/src"
145
+ "contentHash": "abfa1b559afda73ac70b685e2d9bae00fbcc250806fbd1369f9f189fd040e0ca"
137
146
  }
138
- }
147
+ }