@klarkxy/dsh-zhihu 0.2.0 → 0.2.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/lib/client.js CHANGED
@@ -9,6 +9,92 @@ let react = require("react");
9
9
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
11
  //#region src/client-locale.ts
12
+ const responseErrors = {
13
+ "RPC 返回格式无效。": "Invalid RPC response format.",
14
+ "开放平台响应格式无效。": "Invalid Open Platform response format.",
15
+ "响应额度项无效。": "Invalid quota item in the response.",
16
+ "分页响应格式无效。": "Invalid paging response format.",
17
+ "请求已取消": "Request cancelled",
18
+ "查询不超过 4000 字符": "The query must be non-empty and no longer than 4,000 characters",
19
+ "缺少文件内容。": "File content is missing.",
20
+ "文件内容无效或超过 20 MB": "File content is invalid or exceeds 20 MB",
21
+ "搜索词不能为空。": "Search keywords cannot be empty.",
22
+ "知识库文件名不能为空。": "The knowledge base file name cannot be empty.",
23
+ "知识库文件名不能包含控制字符。": "The knowledge base file name cannot contain control characters.",
24
+ "知识库文件名不能超过 255 个 UTF-8 字节。": "The knowledge base file name cannot exceed 255 UTF-8 bytes.",
25
+ "知识库文件内容不能为空。": "The knowledge base file content cannot be empty.",
26
+ "知识库文件大小不能超过 20MB。": "The knowledge base file cannot exceed 20 MB.",
27
+ "当前环境没有可用的 fetch。": "No fetch implementation is available in this environment.",
28
+ "知乎响应缺少 {Code,Message,Data} 信封。": "The Zhihu response has no {Code,Message,Data} envelope.",
29
+ "知乎响应缺少有效的 Code 字段。": "The Zhihu response has no valid Code field.",
30
+ "知乎直答响应不是 OpenAI 兼容格式。": "The Zhihu direct answer response is not in an OpenAI-compatible format.",
31
+ "知乎直答返回为空。": "The Zhihu direct answer response is empty.",
32
+ "分页信息不完整:缺少有效的 Paging.IsEnd,请停止翻页。": "Paging is incomplete: no valid Paging.IsEnd. Stop paging.",
33
+ "分页信息不完整:NextOffset 缺失、无效或未前进,请停止翻页;不要按条数计算偏移。": "Paging is incomplete: NextOffset is missing, invalid or did not advance. Stop paging; do not calculate an offset from item counts.",
34
+ "只允许请求知乎开放平台。": "Only Zhihu Open Platform requests are allowed.",
35
+ "参数必须是对象。": "Parameters must be an object.",
36
+ "这些接口仅使用当前 Access Secret,不接受 token 参数或 OAuth 身份切换。": "These APIs use the current Access Secret only; token parameters and OAuth identity switching are not supported.",
37
+ "offset 超出 Int64 范围。": "offset exceeds the Int64 range.",
38
+ "questionUrl 不能为空。": "questionUrl cannot be empty.",
39
+ "contentUrl 不能为空。": "contentUrl cannot be empty.",
40
+ "知乎链接不能包含空白、控制字符或反斜线。": "Zhihu links cannot contain whitespace, control characters or backslashes.",
41
+ "不是有效的知乎 URL。": "Invalid Zhihu URL.",
42
+ "必须使用无账号密码、无非标准端口的 HTTPS 知乎链接。": "Use an HTTPS Zhihu link without credentials or a non-standard port.",
43
+ "questionUrl 仅支持 https://www.zhihu.com/question/{id}。": "questionUrl only supports https://www.zhihu.com/question/{id}.",
44
+ "contentUrl 仅支持知乎回答、专栏文章、想法或视频链接。": "contentUrl only supports Zhihu answer, article, pin or video links.",
45
+ "startDate 与 endDate 必须同时提供或同时省略。": "Provide both startDate and endDate, or omit both.",
46
+ "endDate 不得早于 startDate。": "endDate cannot be before startDate.",
47
+ "主题关键词不能为空;省略 query 才会按画像推荐。": "Topic keywords cannot be empty; omit query to get profile-based recommendations.",
48
+ "contentType 必须是 all、answer、article、pin 或 zvideo。": "contentType must be all, answer, article, pin or zvideo.",
49
+ "apiIds 包含未知官方额度项。": "apiIds contains unknown official quota items.",
50
+ "order 必须是 score、reverse 或 ascending。": "order must be score, reverse or ascending."
51
+ };
52
+ const operationLabels = {
53
+ "知乎搜索": "Zhihu search",
54
+ "知乎全网搜索": "Zhihu web search",
55
+ "知乎热榜": "Zhihu trending",
56
+ "知乎直答": "Zhihu direct answer",
57
+ "知乎知识库列表": "Zhihu knowledge base list",
58
+ "知乎知识库检索": "Zhihu knowledge base search",
59
+ "知乎知识库上传": "Zhihu knowledge base upload",
60
+ "适合回答的问题": "Questions to answer",
61
+ "问题回答摘要": "Answer summaries",
62
+ "本人创作全文": "My full content",
63
+ "本人创作评论": "Comments on my content",
64
+ "账号创作数据": "Account creator stats",
65
+ "单篇创作数据": "Per-post creator stats",
66
+ "官方每日额度": "Official daily quota"
67
+ };
68
+ function diagnosticText(text, t) {
69
+ if (responseErrors[text]) return t(text, responseErrors[text]);
70
+ const upstream = text.match(/^知乎开放平台返回错误(code=(\d+)):(.*)$/s);
71
+ if (upstream) return t(text, `Zhihu Open Platform returned an error (code=${upstream[1]}): ${upstream[2]}`);
72
+ const blocked = text.match(/^知乎开放平台被风控拒绝:(.*)。请不要立即重试。$/s);
73
+ if (blocked) return t(text, `Zhihu Open Platform rejected the request through risk control: ${blocked[1]}. Do not retry immediately.`);
74
+ for (const [label, english] of Object.entries(operationLabels)) {
75
+ if (!text.startsWith(label)) continue;
76
+ const detail = text.slice(label.length);
77
+ const http = detail.match(/^返回 HTTP (\d{3})。$/);
78
+ if (http) return t(text, `${english} returned HTTP ${http[1]}.`);
79
+ const timeout = detail.match(/^超时((\d+) 秒),请稍后再试。$/);
80
+ if (timeout) return t(text, `${english} timed out (${timeout[1]} seconds). Try again later.`);
81
+ if (detail === "响应不是合法 JSON。") return t(text, `${english} did not return valid JSON.`);
82
+ if (detail === "的 Data 必须是 JSON 对象。") return t(text, `${english} Data must be a JSON object.`);
83
+ if (detail.startsWith("失败:")) return t(text, `${english} failed: ${detail.slice(3)}`);
84
+ if (detail.startsWith("返回错误:")) return t(text, `${english} returned an error: ${detail.slice(5)}`);
85
+ }
86
+ return text;
87
+ }
88
+ function clientText(text, t) {
89
+ if (typeof text !== "string") return t(text[0], text[1]);
90
+ const separator = text.indexOf(":");
91
+ if (separator > 0 && /^[a-z-]+$/.test(text.slice(0, separator))) {
92
+ const code = text.slice(0, separator);
93
+ if (code === "token-missing") return t("未配置有效的知乎 Access Secret,请到设置页配置。", "A valid Zhihu Access Secret is missing. Configure it on the Settings tab.");
94
+ return `${code}: ${diagnosticText(text.slice(separator + 1), t)}`;
95
+ }
96
+ return diagnosticText(text, t);
97
+ }
12
98
  function zhihuLocale(value) {
13
99
  return String(value ?? "zh").startsWith("zh") ? "zh" : "en";
14
100
  }
@@ -42,13 +128,14 @@ const ZHIHU_QUOTA_IDS = [
42
128
  "global_search",
43
129
  "zhihu_search",
44
130
  "hot_list",
45
- "question_answers",
131
+ "question_discovery",
46
132
  "zhida_openai",
47
133
  "tools",
48
134
  "knowledge",
49
135
  "user_data",
50
136
  "creator"
51
137
  ];
138
+ const normalizeZhihuQuotaId = (value) => value === "question_answers" ? "question_discovery" : value;
52
139
  //#endregion
53
140
  //#region src/client-state.ts
54
141
  /**
@@ -387,7 +474,7 @@ ${scope} {
387
474
  border: 0.5px solid var(--dsw-alias-border-l3);
388
475
  border-radius: var(--dsw-radius-md);
389
476
  background: var(--dsw-alias-bg-layer-1);
390
- font-family: var(--ds-font-family-code, ui-monospace, 'Cascadia Mono', Consolas, monospace);
477
+ font-family: var(--ds-font-family-code);
391
478
  font-size: 12px;
392
479
  line-height: 20px;
393
480
  color: var(--dsw-alias-label-secondary);
@@ -686,38 +773,14 @@ function zhihuQueryKeyDown(event, run) {
686
773
  run.search();
687
774
  }
688
775
  }
689
- function hostComponentsFromRenderProps(props) {
690
- if (!props || typeof props !== "object") return {};
691
- const record = props;
692
- const sources = [record];
693
- if (record.owner && typeof record.owner === "object") sources.push(record.owner);
694
- let Select;
695
- let Dialog;
696
- let Button;
697
- let Input;
698
- for (const source of sources) {
699
- if (typeof source.Select === "function") Select = source.Select;
700
- if (typeof source.Dialog === "function") Dialog = source.Dialog;
701
- if (typeof source.Button === "function") Button = source.Button;
702
- if (typeof source.Input === "function") Input = source.Input;
703
- }
704
- return {
705
- Select,
706
- Dialog,
707
- Button,
708
- Input
709
- };
710
- }
711
- function renderInput(Input, props) {
712
- if (Input) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Input, { ...props });
713
- const { onChange, ref, ...rest } = props;
776
+ function renderInput(props) {
777
+ const { onChange, ...rest } = props;
714
778
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
715
779
  ...rest,
716
780
  onChange: (event) => onChange(event.target.value)
717
781
  });
718
782
  }
719
- function renderSelect(Select, props, className) {
720
- if (Select) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Select, { ...props });
783
+ function renderSelect(props, className = "dsh-ui-select") {
721
784
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
722
785
  id: props.id,
723
786
  className,
@@ -731,28 +794,14 @@ function renderSelect(Select, props, className) {
731
794
  }, option.value === "" ? "__empty" : option.value))
732
795
  });
733
796
  }
734
- /**
735
- * The host's own Button still wins whenever the slot supplies one, so a page
736
- * rendered inside DSH keeps the surrounding chrome. Standalone there is no host
737
- * to defer to, and the plugin renders the official primitive instead of a
738
- * hand-rolled `<button>`: the two legacy variant names the call sites use are
739
- * mapped onto it here. `danger` has no primitive variant, so it keeps the
740
- * outlined appearance and takes its tone from a class in the plugin stylesheet
741
- * — the way every other destructive action in the host reads.
742
- */
797
+ /** Map existing plugin variants onto the injected official Button. */
743
798
  const BUTTON_VARIANT = {
744
799
  default: "outline",
745
800
  primary: "primary",
746
801
  danger: "outline",
747
802
  icon: "ghost"
748
803
  };
749
- const ZhihuButton = (0, react.forwardRef)(function ZhihuButton({ host, variant, className, ...rest }, ref) {
750
- if (host) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(host, {
751
- ref,
752
- variant,
753
- className,
754
- ...rest
755
- });
804
+ const ZhihuButton = (0, react.forwardRef)(function ZhihuButton({ variant, className, ...rest }, ref) {
756
805
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
757
806
  ref,
758
807
  variant: BUTTON_VARIANT[variant ?? "default"],
@@ -795,7 +844,7 @@ const OPERATION_COPY = [
795
844
  },
796
845
  {
797
846
  value: "quota",
798
- zh: "官方每日额度",
847
+ zh: "官方每日免费额度",
799
848
  en: "Official daily quota"
800
849
  }
801
850
  ];
@@ -901,6 +950,10 @@ function buildOpenPlatformParams(operation, form, t = translator()) {
901
950
  }
902
951
  }
903
952
  if (operation === "quota") {
953
+ if (Array.isArray(form.apiIds)) form = {
954
+ ...form,
955
+ apiIds: form.apiIds.map((value) => normalizeZhihuQuotaId(value))
956
+ };
904
957
  if (!Array.isArray(form.apiIds) || form.apiIds.some((id) => !ZHIHU_QUOTA_IDS.includes(id))) throw new Error(t("包含未知的额度项。", "Contains an unknown quota item."));
905
958
  if (form.apiIds.length) params.apiIds = [...new Set(form.apiIds)];
906
959
  }
@@ -920,9 +973,12 @@ function parseOpenPlatformResponse(operation, raw) {
920
973
  }
921
974
  const value = raw.value;
922
975
  if (!isRecord(value) || value.version !== 1 || value.operation !== operation || !isRecord(value.data) || !jsonValue(value.data)) throw new Error("开放平台响应格式无效。");
923
- if (value.quotaId !== void 0 && !ZHIHU_QUOTA_IDS.includes(value.quotaId)) throw new Error("响应额度项无效。");
976
+ if (value.quotaId !== void 0 && !ZHIHU_QUOTA_IDS.includes(normalizeZhihuQuotaId(value.quotaId))) throw new Error("响应额度项无效。");
924
977
  if (value.paging !== void 0 && (!isRecord(value.paging) || typeof value.paging.canContinue !== "boolean" || value.paging.isEnd !== void 0 && typeof value.paging.isEnd !== "boolean" || value.paging.warning !== void 0 && typeof value.paging.warning !== "string")) throw new Error("分页响应格式无效。");
925
- return value;
978
+ return {
979
+ ...value,
980
+ ...value.quotaId === void 0 ? {} : { quotaId: normalizeZhihuQuotaId(value.quotaId) }
981
+ };
926
982
  }
927
983
  function openPlatformNextOffset(result, currentOffset) {
928
984
  if (!result || !["question.answers", "content.comments"].includes(result.operation) || result.paging?.canContinue !== true || result.paging.isEnd === true) return null;
@@ -941,7 +997,7 @@ async function requestOpenPlatform(rpc, state, operation, params, publish) {
941
997
  if (state.isCurrent(ticket)) publish({ error: error instanceof Error ? error.message : String(error) });
942
998
  }
943
999
  }
944
- function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = false, selectedOperation }) {
1000
+ function ZhihuOpenPlatformSection({ rpc, quotaOnly = false, selectedOperation }) {
945
1001
  const t = useT();
946
1002
  const [operation, setOperation] = (0, react.useState)(quotaOnly ? "quota" : "question.recommendations");
947
1003
  const [form, setForm] = (0, react.useState)(createOpenPlatformForm);
@@ -992,7 +1048,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
992
1048
  className: "dsh-ui-label",
993
1049
  children: label
994
1050
  }),
995
- renderInput(Input, {
1051
+ renderInput({
996
1052
  value: form[key],
997
1053
  onChange: (value) => change(key, value),
998
1054
  "aria-label": label,
@@ -1015,7 +1071,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1015
1071
  className: "dsh-ui-label",
1016
1072
  children: label
1017
1073
  }),
1018
- renderSelect(Select, {
1074
+ renderSelect({
1019
1075
  value: form[key],
1020
1076
  onChange: (value) => change(key, value),
1021
1077
  "aria-label": label,
@@ -1034,9 +1090,17 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1034
1090
  offset
1035
1091
  };
1036
1092
  try {
1037
- params = buildOpenPlatformParams(activeOperation, nextForm, t);
1038
- } catch (cause) {
1039
- setError(cause instanceof Error ? cause.message : String(cause));
1093
+ params = buildOpenPlatformParams(activeOperation, nextForm);
1094
+ } catch {
1095
+ const message = (locale) => {
1096
+ try {
1097
+ buildOpenPlatformParams(activeOperation, nextForm, translator(locale));
1098
+ return "";
1099
+ } catch (cause) {
1100
+ return cause instanceof Error ? cause.message : String(cause);
1101
+ }
1102
+ };
1103
+ setError([message("zh"), message("en")]);
1040
1104
  return;
1041
1105
  }
1042
1106
  if (offset !== void 0) setForm(nextForm);
@@ -1054,7 +1118,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1054
1118
  const paged = activeOperation === "question.answers" || activeOperation === "content.comments";
1055
1119
  const dated = activeOperation === "creator.account.stats" || activeOperation === "creator.content.stats";
1056
1120
  const options = openPlatformOptions(t);
1057
- const title = quotaOnly ? t("官方每日额度", "Official daily quota") : t("问题与创作", "Questions and creator");
1121
+ const title = quotaOnly ? t("官方每日免费额度", "Official daily quota") : t("问题与创作", "Questions and creator");
1058
1122
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1059
1123
  className: "zhihu-open-platform dsh-ui-stack",
1060
1124
  "aria-label": title,
@@ -1067,7 +1131,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1067
1131
  className: "dsh-ui-help",
1068
1132
  children: quotaOnly ? t("查询知乎返回的官方额度,不推算余额。", "Shows the quota Zhihu reports; no balance is inferred.") : t("手动触发,不自动翻页或重试。", "Manual trigger only; no automatic paging or retry.")
1069
1133
  }),
1070
- !quotaOnly && selectedOperation === void 0 && renderSelect(Select, {
1134
+ !quotaOnly && selectedOperation === void 0 && renderSelect({
1071
1135
  value: activeOperation,
1072
1136
  options,
1073
1137
  "aria-label": t("开放平台操作", "Open Platform operation"),
@@ -1156,23 +1220,20 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1156
1220
  className: "dsh-ui-actions",
1157
1221
  children: [
1158
1222
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1159
- host: Button,
1160
1223
  variant: "primary",
1161
1224
  disabled: loading,
1162
1225
  onClick: () => run(),
1163
1226
  children: activeOperation === "quota" ? t("查询官方额度", "Check quota") : t("执行请求", "Run request")
1164
1227
  }),
1165
1228
  loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1166
- host: Button,
1167
1229
  onClick: () => {
1168
1230
  state.cancel();
1169
1231
  setLoading(false);
1170
- setError(t("已取消;晚到的结果将被丢弃。", "Cancelled; a late response will be discarded."));
1232
+ setError(["已取消;晚到的结果将被丢弃。", "Cancelled; a late response will be discarded."]);
1171
1233
  },
1172
1234
  children: t("取消请求", "Cancel")
1173
1235
  }),
1174
1236
  nextOffset !== null && !loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1175
- host: Button,
1176
1237
  onClick: () => run(nextOffset),
1177
1238
  children: t("下一页", "Next page")
1178
1239
  })
@@ -1186,7 +1247,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1186
1247
  error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1187
1248
  className: "dsh-ui-error",
1188
1249
  role: "alert",
1189
- children: error
1250
+ children: clientText(error, t)
1190
1251
  }),
1191
1252
  result && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1192
1253
  className: "dsh-ui-stack",
@@ -1201,7 +1262,7 @@ function ZhihuOpenPlatformSection({ rpc, Button, Input, Select, quotaOnly = fals
1201
1262
  }),
1202
1263
  result.paging?.warning && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1203
1264
  className: "dsh-ui-banner",
1204
- children: result.paging.warning
1265
+ children: clientText(result.paging.warning, t)
1205
1266
  }),
1206
1267
  !stale && paged && result.paging?.canContinue && nextOffset === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1207
1268
  className: "dsh-ui-banner",
@@ -1234,6 +1295,52 @@ function OpenPlatformDetails({ quotaOnly }) {
1234
1295
  });
1235
1296
  }
1236
1297
  //#endregion
1298
+ //#region src/client-call-policy.tsx
1299
+ function ZhihuCallPolicySummary({ policy }) {
1300
+ const t = useT();
1301
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1302
+ className: "dsh-ui-help",
1303
+ children: t(`${policy.allowPaid ? "已显式允许付费" : "仅使用免费额度"} · 每日上限 ${policy.dailyCallLimit} 次(北京时间)`, `${policy.allowPaid ? "Paid calls explicitly enabled" : "Free allowance only"} · ${policy.dailyCallLimit} calls per Beijing day`)
1304
+ });
1305
+ }
1306
+ function ZhihuCallPolicySection({ rpc }) {
1307
+ const t = useT();
1308
+ const [policy, setPolicy] = (0, react.useState)(null);
1309
+ const [failed, setFailed] = (0, react.useState)(false);
1310
+ (0, react.useEffect)(() => {
1311
+ let alive = true;
1312
+ rpc.call(ZHIHU_RPC_CHANNEL, "policy.status", {}).then((result) => {
1313
+ if (!alive) return;
1314
+ const value = result;
1315
+ if (value?.ok && typeof value.value?.allowPaid === "boolean" && typeof value.value.dailyCallLimit === "number") setPolicy(value.value);
1316
+ else setFailed(true);
1317
+ }, () => {
1318
+ if (alive) setFailed(true);
1319
+ });
1320
+ return () => {
1321
+ alive = false;
1322
+ };
1323
+ }, [rpc]);
1324
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1325
+ className: "dsh-ui-stack",
1326
+ "aria-label": t("调用保护", "Call protection"),
1327
+ children: [
1328
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
1329
+ className: "dsh-ui-heading",
1330
+ children: t("调用保护", "Call protection")
1331
+ }),
1332
+ policy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuCallPolicySummary, { policy }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1333
+ className: "dsh-ui-help",
1334
+ children: failed ? t("保护配置不可用;请检查插件配置。", "Protection settings unavailable. Check plugin configuration.") : t("读取保护配置…", "Loading protection settings…")
1335
+ }),
1336
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1337
+ className: "dsh-ui-hint",
1338
+ children: t("付费须在插件配置显式启用。未确认计费的能力仅允许使用已确认的免费额度。本地保护无法排除同账号其他客户端竞争导致的扣费;调用统计不是账单。", "Enable paid calls explicitly in plugin configuration. Unpriced capabilities require verified free allowance. Other clients on the same account can still cause charges; local counts are not billing.")
1339
+ })
1340
+ ]
1341
+ });
1342
+ }
1343
+ //#endregion
1237
1344
  //#region src/client-quota.tsx
1238
1345
  const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1239
1346
  const identityFields = /* @__PURE__ */ new Set([
@@ -1508,7 +1615,7 @@ function QuotaCharts({ data }) {
1508
1615
  ]
1509
1616
  });
1510
1617
  }
1511
- function ZhihuQuotaSection({ rpc, Button }) {
1618
+ function ZhihuQuotaSection({ rpc }) {
1512
1619
  const state = (0, react.useRef)(createZhihuClientState()).current;
1513
1620
  const [snapshot, setSnapshot] = (0, react.useState)(null);
1514
1621
  const [loading, setLoading] = (0, react.useState)(false);
@@ -1537,7 +1644,7 @@ function ZhihuQuotaSection({ rpc, Button }) {
1537
1644
  refresh();
1538
1645
  return () => state.cancel();
1539
1646
  }, [refresh, state]);
1540
- const title = t("官方额度用量", "Official quota");
1647
+ const title = t("官方免费额度用量", "Official quota");
1541
1648
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1542
1649
  className: "dsh-ui-stack",
1543
1650
  "aria-label": title,
@@ -1557,17 +1664,15 @@ function ZhihuQuotaSection({ rpc, Button }) {
1557
1664
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1558
1665
  className: "dsh-ui-actions",
1559
1666
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1560
- host: Button,
1561
1667
  variant: "primary",
1562
1668
  disabled: loading,
1563
1669
  onClick: refresh,
1564
1670
  children: t("刷新官方额度", "Refresh quota")
1565
1671
  }), loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
1566
- host: Button,
1567
1672
  onClick: () => {
1568
1673
  state.cancel();
1569
1674
  setLoading(false);
1570
- setError(t("已取消;晚到的结果将被丢弃。", "Cancelled; a late response will be discarded."));
1675
+ setError(["已取消;晚到的结果将被丢弃。", "Cancelled; a late response will be discarded."]);
1571
1676
  },
1572
1677
  children: t("取消请求", "Cancel")
1573
1678
  })]
@@ -1580,7 +1685,7 @@ function ZhihuQuotaSection({ rpc, Button }) {
1580
1685
  error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1581
1686
  className: "dsh-ui-error",
1582
1687
  role: "alert",
1583
- children: error
1688
+ children: clientText(error, t)
1584
1689
  }),
1585
1690
  snapshot && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1586
1691
  className: "dsh-ui-stack",
@@ -1611,7 +1716,6 @@ const inject = [
1611
1716
  ];
1612
1717
  const PACKAGE_NAME = "@klarkxy/dsh-zhihu";
1613
1718
  const SLOT_ORDER = 120;
1614
- const SLOT_LABEL = "知乎";
1615
1719
  const activityDots = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1616
1720
  className: "zhihu-dots",
1617
1721
  "aria-hidden": "true",
@@ -1651,21 +1755,21 @@ function safeUrl(url) {
1651
1755
  return /^https?:\/\//i.test(url) ? url : null;
1652
1756
  }
1653
1757
  /** Credential absence and transport failure read differently from a plain bad request. */
1654
- function failureOf(code, message, t = translator()) {
1758
+ function failureOf(code, message) {
1655
1759
  if (code === "token-missing") return {
1656
1760
  kind: "credential",
1657
- text: t("未配置知乎 Access Secret 或凭证不可用,请到「设置」页配置。", "Zhihu Access Secret is missing or unavailable. Set it on the Settings tab.")
1761
+ text: ["未配置知乎 Access Secret 或凭证不可用,请到「设置」页配置。", "Zhihu Access Secret is missing or unavailable. Set it on the Settings tab."]
1658
1762
  };
1659
1763
  return {
1660
1764
  kind: "request",
1661
- text: t(`请求失败:${message}`, `Request failed: ${message}`)
1765
+ text: [`请求失败:${clientText(message, translator("zh"))}`, `Request failed: ${clientText(message, translator("en"))}`]
1662
1766
  };
1663
1767
  }
1664
- function networkFailure(cause, t = translator()) {
1768
+ function networkFailure(cause) {
1665
1769
  const detail = cause instanceof Error ? cause.message : String(cause);
1666
1770
  return {
1667
1771
  kind: "network",
1668
- text: t(`网络或连接失败:${detail}`, `Network or connection failed: ${detail}`)
1772
+ text: [`网络或连接失败:${detail}`, `Network or connection failed: ${detail}`]
1669
1773
  };
1670
1774
  }
1671
1775
  /**
@@ -1718,10 +1822,10 @@ function testOptions(t) {
1718
1822
  })), ...openPlatformOptions(t).filter((option) => option.value !== "quota")];
1719
1823
  }
1720
1824
  const TEST_OPTIONS = testOptions(translator("zh"));
1721
- function ZhihuTestSelector({ value, onChange, Select }) {
1825
+ function ZhihuTestSelector({ value, onChange }) {
1722
1826
  const t = useT();
1723
1827
  const options = testOptions(t);
1724
- return renderSelect(Select, {
1828
+ return renderSelect({
1725
1829
  "aria-label": t("测试功能", "Feature to test"),
1726
1830
  value,
1727
1831
  options,
@@ -2055,11 +2159,10 @@ function SettingsSection(props) {
2055
2159
  if (state.status === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SettingsShell, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2056
2160
  className: "dsh-ui-error",
2057
2161
  role: "alert",
2058
- children: t(`读取失败:${state.error}`, `Could not load: ${state.error}`)
2162
+ children: t(`读取失败:${clientText(state.error, t)}`, `Could not load: ${clientText(state.error, t)}`)
2059
2163
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2060
2164
  className: "dsh-ui-actions",
2061
2165
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2062
- host: props.Button,
2063
2166
  onClick: () => void load(),
2064
2167
  children: t("重试", "Retry")
2065
2168
  })
@@ -2088,7 +2191,7 @@ function SettingsSection(props) {
2088
2191
  return;
2089
2192
  }
2090
2193
  setKeyDraft("");
2091
- setNote(t("已保存。", "Saved."));
2194
+ setNote(["已保存。", "Saved."]);
2092
2195
  await load();
2093
2196
  } catch (cause) {
2094
2197
  if (!alive.current) return;
@@ -2111,7 +2214,7 @@ function SettingsSection(props) {
2111
2214
  return;
2112
2215
  }
2113
2216
  setKeyDraft("");
2114
- setNote(t("已清除。", "Cleared."));
2217
+ setNote(["已清除。", "Cleared."]);
2115
2218
  await load();
2116
2219
  } catch (cause) {
2117
2220
  if (!alive.current) return;
@@ -2142,7 +2245,7 @@ function SettingsSection(props) {
2142
2245
  children: t("获取密钥", "Get a key")
2143
2246
  })]
2144
2247
  }),
2145
- renderInput(props.Input, {
2248
+ renderInput({
2146
2249
  type: "password",
2147
2250
  className: "zhihu-input",
2148
2251
  value: keyDraft,
@@ -2161,24 +2264,22 @@ function SettingsSection(props) {
2161
2264
  failure !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2162
2265
  className: "dsh-ui-error",
2163
2266
  role: "alert",
2164
- children: failure
2267
+ children: clientText(failure, t)
2165
2268
  }) : null,
2166
2269
  note !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2167
2270
  className: "dsh-ui-notice",
2168
2271
  role: "status",
2169
- children: note
2272
+ children: clientText(note, t)
2170
2273
  }) : null,
2171
2274
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2172
2275
  className: "dsh-ui-actions",
2173
2276
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2174
- host: props.Button,
2175
2277
  variant: "danger",
2176
2278
  className: "zhihu-button-danger",
2177
2279
  disabled: busy || keyLocked || !configured,
2178
2280
  onClick: () => setConfirmClear(true),
2179
2281
  children: pending === "clear" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [activityDots(), t("清除中…", "Clearing…")] }) : t("清除", "Clear")
2180
2282
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2181
- host: props.Button,
2182
2283
  variant: "primary",
2183
2284
  disabled: busy || keyLocked || keyValue.length === 0 || draftFailure !== void 0,
2184
2285
  onClick: () => void save(),
@@ -2194,11 +2295,9 @@ function SettingsSection(props) {
2194
2295
  footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2195
2296
  className: "dsh-ui-actions",
2196
2297
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2197
- host: props.Button,
2198
2298
  onClick: () => setConfirmClear(false),
2199
2299
  children: t("取消", "Cancel")
2200
2300
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2201
- host: props.Button,
2202
2301
  variant: "danger",
2203
2302
  className: "zhihu-button-danger",
2204
2303
  onClick: () => void clear(),
@@ -2434,7 +2533,7 @@ function UsageSection(props) {
2434
2533
  if (!isUsageSummary(result.value)) {
2435
2534
  setState({
2436
2535
  status: "error",
2437
- error: "invalid response shape"
2536
+ error: ["响应格式与契约不符。", "The response does not match the expected shape."]
2438
2537
  });
2439
2538
  return;
2440
2539
  }
@@ -2470,11 +2569,10 @@ function UsageSection(props) {
2470
2569
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2471
2570
  className: "dsh-ui-error",
2472
2571
  role: "alert",
2473
- children: t(`读取失败:${state.error}`, `Could not load: ${state.error}`)
2572
+ children: t(`读取失败:${clientText(state.error, t)}`, `Could not load: ${clientText(state.error, t)}`)
2474
2573
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2475
2574
  className: "dsh-ui-actions",
2476
2575
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2477
- host: props.Button,
2478
2576
  onClick: () => void load(),
2479
2577
  children: t("重试", "Retry")
2480
2578
  })
@@ -2495,7 +2593,6 @@ function UsageSection(props) {
2495
2593
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2496
2594
  className: "dsh-ui-actions",
2497
2595
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2498
- host: props.Button,
2499
2596
  onClick: () => void load(),
2500
2597
  children: t("刷新统计", "Refresh")
2501
2598
  })
@@ -2656,7 +2753,7 @@ function KnowledgeSection(props) {
2656
2753
  if (!result.ok) {
2657
2754
  setList({
2658
2755
  status: "error",
2659
- failure: failureOf(result.error.code, result.error.message, t)
2756
+ failure: failureOf(result.error.code, result.error.message)
2660
2757
  });
2661
2758
  return;
2662
2759
  }
@@ -2665,7 +2762,7 @@ function KnowledgeSection(props) {
2665
2762
  status: "error",
2666
2763
  failure: {
2667
2764
  kind: "request",
2668
- text: t("响应格式与契约不符。", "The response does not match the expected shape.")
2765
+ text: ["响应格式与契约不符。", "The response does not match the expected shape."]
2669
2766
  }
2670
2767
  });
2671
2768
  return;
@@ -2678,14 +2775,10 @@ function KnowledgeSection(props) {
2678
2775
  if (!gate.isCurrent(ticket)) return;
2679
2776
  setList({
2680
2777
  status: "error",
2681
- failure: networkFailure(cause, t)
2778
+ failure: networkFailure(cause)
2682
2779
  });
2683
2780
  }
2684
- }, [
2685
- gate,
2686
- rpc,
2687
- t
2688
- ]);
2781
+ }, [gate, rpc]);
2689
2782
  (0, react.useEffect)(() => {
2690
2783
  load();
2691
2784
  }, [load]);
@@ -2694,7 +2787,7 @@ function KnowledgeSection(props) {
2694
2787
  setFailure(void 0);
2695
2788
  setNote(void 0);
2696
2789
  if (file.size > KB_MAX_BYTES) {
2697
- setFailure(t("文件超过 20 MB 上限。", "The file exceeds the 20 MB limit."));
2790
+ setFailure(["文件超过 20 MB 上限。", "The file exceeds the 20 MB limit."]);
2698
2791
  return;
2699
2792
  }
2700
2793
  const { ticket, signal } = gate.begin();
@@ -2710,17 +2803,17 @@ function KnowledgeSection(props) {
2710
2803
  if (!gate.isCurrent(ticket)) return;
2711
2804
  const result = raw;
2712
2805
  if (!result.ok) {
2713
- setFailure(t(`上传失败:${result.error.message}`, `Upload failed: ${result.error.message}`));
2806
+ setFailure([`上传失败:${result.error.message}`, `Upload failed: ${result.error.message}`]);
2714
2807
  return;
2715
2808
  }
2716
- setNote(t("已上传到知乎知识库。", "Uploaded to the Zhihu knowledge base."));
2809
+ setNote(["已上传到知乎知识库。", "Uploaded to the Zhihu knowledge base."]);
2717
2810
  setFile(void 0);
2718
2811
  setFileKey((key) => key + 1);
2719
2812
  await load();
2720
2813
  } catch (cause) {
2721
2814
  if (!gate.isCurrent(ticket)) return;
2722
2815
  const detail = cause instanceof Error ? cause.message : String(cause);
2723
- setFailure(t(`上传失败:${detail}`, `Upload failed: ${detail}`));
2816
+ setFailure([`上传失败:${detail}`, `Upload failed: ${detail}`]);
2724
2817
  } finally {
2725
2818
  setBusy(false);
2726
2819
  }
@@ -2749,11 +2842,10 @@ function KnowledgeSection(props) {
2749
2842
  list.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2750
2843
  className: "dsh-ui-error",
2751
2844
  role: "alert",
2752
- children: list.failure.text
2845
+ children: clientText(list.failure.text, t)
2753
2846
  }), list.failure.kind !== "credential" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2754
2847
  className: "dsh-ui-actions",
2755
2848
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2756
- host: props.Button,
2757
2849
  onClick: () => void load(),
2758
2850
  children: t("重试", "Retry")
2759
2851
  })
@@ -2768,7 +2860,7 @@ function KnowledgeSection(props) {
2768
2860
  }),
2769
2861
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2770
2862
  className: "dsh-ui-row",
2771
- children: [renderSelect(props.Select, {
2863
+ children: [renderSelect({
2772
2864
  id: "zhihu-kb-base",
2773
2865
  value: baseId,
2774
2866
  disabled: busy,
@@ -2782,7 +2874,6 @@ function KnowledgeSection(props) {
2782
2874
  label: t(`${base.name}${base.isDefault ? "(默认)" : ""} · ${base.contentCount} 篇`, `${base.name}${base.isDefault ? " (default)" : ""} · ${base.contentCount} docs`)
2783
2875
  }))]
2784
2876
  }, "dsh-ui-select"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2785
- host: props.Button,
2786
2877
  disabled: busy,
2787
2878
  onClick: () => void load(),
2788
2879
  children: t("刷新", "Refresh")
@@ -2832,7 +2923,6 @@ function KnowledgeSection(props) {
2832
2923
  list.status === "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2833
2924
  className: "dsh-ui-actions",
2834
2925
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
2835
- host: props.Button,
2836
2926
  variant: "primary",
2837
2927
  disabled: busy || !file,
2838
2928
  onClick: () => void upload(),
@@ -2842,12 +2932,12 @@ function KnowledgeSection(props) {
2842
2932
  note ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2843
2933
  className: "dsh-ui-notice",
2844
2934
  role: "status",
2845
- children: note
2935
+ children: clientText(note, t)
2846
2936
  }) : null,
2847
2937
  failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2848
2938
  className: "dsh-ui-error",
2849
2939
  role: "alert",
2850
- children: failure
2940
+ children: clientText(failure, t)
2851
2941
  }) : null
2852
2942
  ]
2853
2943
  });
@@ -2876,7 +2966,7 @@ function nextVisitedTabs(visited, next) {
2876
2966
  return visited.includes(next) ? [...visited] : [...visited, next];
2877
2967
  }
2878
2968
  function ZhihuSettings(props) {
2879
- const { rpc, credentials, Select, Button, Input } = props;
2969
+ const { rpc, credentials } = props;
2880
2970
  const t = useT();
2881
2971
  const gateRef = (0, react.useRef)(null);
2882
2972
  if (!gateRef.current) gateRef.current = createZhihuClientState();
@@ -2922,7 +3012,7 @@ function ZhihuSettings(props) {
2922
3012
  if (!parsed) {
2923
3013
  setFailure({
2924
3014
  kind: "request",
2925
- text: t("响应格式与契约不符。", "The response does not match the expected shape.")
3015
+ text: ["响应格式与契约不符。", "The response does not match the expected shape."]
2926
3016
  });
2927
3017
  setPhase("error");
2928
3018
  return;
@@ -2932,12 +3022,12 @@ function ZhihuSettings(props) {
2932
3022
  setPhase("done");
2933
3023
  } else if (response.error.code === "cancelled") setPhase("idle");
2934
3024
  else {
2935
- setFailure(failureOf(response.error.code, response.error.message, t));
3025
+ setFailure(failureOf(response.error.code, response.error.message));
2936
3026
  setPhase("error");
2937
3027
  }
2938
3028
  } catch (cause) {
2939
3029
  if (!gate.isCurrent(ticket)) return;
2940
- setFailure(networkFailure(cause, t));
3030
+ setFailure(networkFailure(cause));
2941
3031
  setPhase("error");
2942
3032
  }
2943
3033
  }, [
@@ -3021,12 +3111,11 @@ function ZhihuSettings(props) {
3021
3111
  className: "dsh-ui-field",
3022
3112
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuTestSelector, {
3023
3113
  value: testOperation,
3024
- onChange: onTestOperationChange,
3025
- Select
3114
+ onChange: onTestOperationChange
3026
3115
  }), isSearchOperation ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [
3027
3116
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3028
3117
  className: "dsh-ui-row",
3029
- children: mode === "ask" ? renderSelect(Select, {
3118
+ children: mode === "ask" ? renderSelect({
3030
3119
  "aria-label": t("直答模型", "Answer model"),
3031
3120
  value: askModel,
3032
3121
  onChange: (next) => onAskModelChange(next),
@@ -3058,7 +3147,7 @@ function ZhihuSettings(props) {
3058
3147
  id: "zhihu-scope-hint",
3059
3148
  children: t("至少保留一个检索范围。", "Keep at least one scope selected.")
3060
3149
  })] }) : null,
3061
- renderInput(Input, {
3150
+ renderInput({
3062
3151
  type: "search",
3063
3152
  className: "zhihu-input",
3064
3153
  "data-testid": "zhihu-query",
@@ -3072,14 +3161,12 @@ function ZhihuSettings(props) {
3072
3161
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3073
3162
  className: "dsh-ui-actions",
3074
3163
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
3075
- host: Button,
3076
3164
  variant: "primary",
3077
3165
  "data-testid": "zhihu-search",
3078
3166
  disabled: searchDisabled,
3079
3167
  onClick: () => void runSearch(),
3080
3168
  children: mode === "hot" ? t("获取热榜", "Get trending") : t("搜索", "Search")
3081
3169
  }), phase === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuButton, {
3082
- host: Button,
3083
3170
  onClick: () => {
3084
3171
  gate.cancel();
3085
3172
  setPhase("idle");
@@ -3095,7 +3182,7 @@ function ZhihuSettings(props) {
3095
3182
  phase === "error" && failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3096
3183
  className: "dsh-ui-error",
3097
3184
  role: "alert",
3098
- children: failure.text
3185
+ children: clientText(failure.text, t)
3099
3186
  }) : null,
3100
3187
  phase === "done" && outcome ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutcomeView, {
3101
3188
  outcome,
@@ -3103,10 +3190,7 @@ function ZhihuSettings(props) {
3103
3190
  }) : null
3104
3191
  ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuOpenPlatformSection, {
3105
3192
  selectedOperation: testOperation,
3106
- rpc,
3107
- Button,
3108
- Input,
3109
- Select
3193
+ rpc
3110
3194
  }, testOperation)]
3111
3195
  });
3112
3196
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
@@ -3115,24 +3199,10 @@ function ZhihuSettings(props) {
3115
3199
  "aria-label": t("知乎", "Zhihu"),
3116
3200
  children: [
3117
3201
  tablist,
3118
- panel("settings", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsSection, {
3119
- credentials,
3120
- Button,
3121
- Input
3122
- })),
3123
- panel("usage", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
3124
- rpc,
3125
- Button
3126
- })),
3127
- panel("quota", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuQuotaSection, {
3128
- rpc,
3129
- Button
3130
- })),
3131
- panel("knowledge", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KnowledgeSection, {
3132
- rpc,
3133
- Select,
3134
- Button
3135
- })),
3202
+ panel("settings", /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsSection, { credentials }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuCallPolicySection, { rpc })] })),
3203
+ panel("usage", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, { rpc })),
3204
+ panel("quota", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuQuotaSection, { rpc })),
3205
+ panel("knowledge", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KnowledgeSection, { rpc })),
3136
3206
  panel("test", testPanel)
3137
3207
  ]
3138
3208
  });
@@ -3158,17 +3228,15 @@ function apply(ctx) {
3158
3228
  } catch {
3159
3229
  locale = void 0;
3160
3230
  }
3161
- const settingsRender = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuSettingsRoot, {
3231
+ const settingsRender = () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhihuSettingsRoot, {
3162
3232
  rpc: client.connection.rpc,
3163
3233
  credentials: wrapCredentials(client.remote.credentials),
3164
- locale,
3165
- ...hostComponentsFromRenderProps(props)
3234
+ locale
3166
3235
  });
3167
3236
  ctx.effect(() => client.slots.inject("plugins.bundle.config", () => client.slots.register({
3168
3237
  name: "plugins.bundle.config",
3169
3238
  key: PACKAGE_NAME,
3170
- order: SLOT_ORDER,
3171
- label: SLOT_LABEL
3239
+ order: SLOT_ORDER
3172
3240
  }, settingsRender)), "zhihu.settings");
3173
3241
  }
3174
3242
  //#endregion