dsh-zhihu-search 2.0.0 → 2.0.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 +7 -3
- package/README_en.md +7 -3
- package/lib/client.js +51 -59
- package/lib/index.js +2 -2
- package/lib/present/search.js +11 -4
- package/lib/tools/global-search.js +36 -9
- package/lib/tools/search-shared.js +9 -3
- package/lib/tools/search.js +46 -12
- package/lib/tools/zhida.js +13 -2
- package/lib/transport.js +31 -19
- package/lib/types/client/index.d.ts +4 -4
- package/lib/utils/text.js +3 -1
- package/package.json +38 -29
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="icon.svg" alt="dsh-zhihu-search" width="80" height="80">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
<p align="center">
|
|
2
6
|
<h1 align="center">dsh-zhihu-search</h1>
|
|
3
7
|
</p>
|
|
@@ -101,16 +105,16 @@
|
|
|
101
105
|
|
|
102
106
|
### 前置
|
|
103
107
|
|
|
104
|
-
- **DSH `0.1.7-
|
|
108
|
+
- **DSH `0.1.7-rc.2` 或更高,且低于 `0.2.0`** —— 即 [package.json](package.json) 里 `engines.dsh` 与全部 `@deepseek-ai/dsh-*` 共同声明的那条区间(两处**同形状**是硬要求:接缝缺席时配置界面会静默不出现)。
|
|
105
109
|
- Node `>= 20`
|
|
106
110
|
|
|
107
111
|
装宿主时**要显式指定版本线**:本家族的 `latest` 标签不可靠(多数 `@deepseek-ai/dsh-*` 包上它指向很早的版本),按默认方式装可能落在声明范围之外 —— 现查 `npm view @deepseek-ai/dsh dist-tags`。
|
|
108
112
|
|
|
109
113
|
```bash
|
|
110
|
-
npm install -g @deepseek-ai/dsh@
|
|
114
|
+
npm install -g @deepseek-ai/dsh@next # 本插件承诺支持的线
|
|
111
115
|
```
|
|
112
116
|
|
|
113
|
-
兼容性不是推断出来的:每周由 [compat.yml](.github/workflows/compat.yml) 对 `
|
|
117
|
+
兼容性不是推断出来的:每周由 [compat.yml](.github/workflows/compat.yml) 对 `next`(承诺线)与 `alpha`(**已低于我们声明的下限,只作记录**)两条线换包实跑一遍现有测试。当前结论与红了怎么办见 [docs/PUBLISHING.md](docs/PUBLISHING.md) 的「兼容性」。
|
|
114
118
|
|
|
115
119
|
### 从源码安装
|
|
116
120
|
|
package/README_en.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="icon.svg" alt="dsh-zhihu-search" width="80" height="80">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
<p align="center">
|
|
2
6
|
<h1 align="center">dsh-zhihu-search</h1>
|
|
3
7
|
</p>
|
|
@@ -101,16 +105,16 @@ The three sections below are each tool's full parameter set and limits. The mode
|
|
|
101
105
|
|
|
102
106
|
### Requirements
|
|
103
107
|
|
|
104
|
-
- **DSH `0.1.7-
|
|
108
|
+
- **DSH `0.1.7-rc.2` or newer, below `0.2.0`** — the single range that [package.json](package.json) declares in both `engines.dsh` and every `@deepseek-ai/dsh-*` entry (the two must stay the same shape: a missing host seam makes the configuration UI disappear silently).
|
|
105
109
|
- Node `>= 20`
|
|
106
110
|
|
|
107
111
|
Install the Host from an **explicit dist-tag**: `latest` is not trustworthy across this family (on most `@deepseek-ai/dsh-*` packages it points at a much older version), so a default install can land outside the declared range — check it live with `npm view @deepseek-ai/dsh dist-tags`.
|
|
108
112
|
|
|
109
113
|
```bash
|
|
110
|
-
npm install -g @deepseek-ai/dsh@
|
|
114
|
+
npm install -g @deepseek-ai/dsh@next # the line this plugin commits to
|
|
111
115
|
```
|
|
112
116
|
|
|
113
|
-
Compatibility is measured, not inferred: [compat.yml](.github/workflows/compat.yml) swaps the DSH packages onto the `
|
|
117
|
+
Compatibility is measured, not inferred: [compat.yml](.github/workflows/compat.yml) swaps the DSH packages onto the `next` line (the committed one) and the `alpha` line (now **below our declared floor**, kept as a record only) every week, and runs the existing suite. Current results and what to do when a line breaks: [docs/PUBLISHING.md](docs/PUBLISHING.md).
|
|
114
118
|
|
|
115
119
|
### From source
|
|
116
120
|
|
package/lib/client.js
CHANGED
|
@@ -145,35 +145,30 @@ function asRecord(value) {
|
|
|
145
145
|
}
|
|
146
146
|
var S = {
|
|
147
147
|
form: { display: "flex", flexDirection: "column" },
|
|
148
|
-
readOnly: {
|
|
149
|
-
|
|
150
|
-
fieldDivider: { display: "flex", flexDirection: "column", gap: 6, padding: "12px 0", borderTop: "0.5px solid var(--dsw-alias-border-l2)" },
|
|
151
|
-
head: { display: "flex", alignItems: "center", gap: 8 },
|
|
152
|
-
label: { flex: 1, minWidth: 0, fontSize: 13, fontWeight: 500, lineHeight: 1.5, color: "var(--dsw-alias-label-primary)" },
|
|
153
|
-
badges: { display: "inline-flex", alignItems: "center", gap: 8 },
|
|
154
|
-
reset: {
|
|
155
|
-
border: "none",
|
|
156
|
-
background: "none",
|
|
157
|
-
padding: 0,
|
|
158
|
-
font: "inherit",
|
|
148
|
+
readOnly: {
|
|
149
|
+
margin: "12px 0 0",
|
|
159
150
|
fontSize: 12,
|
|
160
151
|
lineHeight: 1.5,
|
|
161
|
-
color: "var(--dsw-alias-label-
|
|
162
|
-
|
|
152
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
153
|
+
},
|
|
154
|
+
field: { display: "flex", flexDirection: "column", gap: 6, padding: "12px 0" },
|
|
155
|
+
fieldDivider: {
|
|
156
|
+
display: "flex",
|
|
157
|
+
flexDirection: "column",
|
|
158
|
+
gap: 6,
|
|
159
|
+
padding: "12px 0",
|
|
160
|
+
borderTop: "0.5px solid var(--dsw-alias-border-l2)"
|
|
163
161
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
borderRadius: 8,
|
|
169
|
-
background: "var(--dsw-alias-bg-layer-3)",
|
|
170
|
-
font: "inherit",
|
|
162
|
+
head: { display: "flex", alignItems: "center", gap: 8 },
|
|
163
|
+
label: {
|
|
164
|
+
flex: 1,
|
|
165
|
+
minWidth: 0,
|
|
171
166
|
fontSize: 13,
|
|
167
|
+
fontWeight: 500,
|
|
172
168
|
lineHeight: 1.5,
|
|
173
|
-
color: "var(--dsw-alias-label-primary)"
|
|
174
|
-
boxSizing: "border-box",
|
|
175
|
-
width: "100%"
|
|
169
|
+
color: "var(--dsw-alias-label-primary)"
|
|
176
170
|
},
|
|
171
|
+
badges: { display: "inline-flex", alignItems: "center", gap: 8 },
|
|
177
172
|
hint: { margin: 0, fontSize: 12, lineHeight: 1.5, color: "var(--dsw-alias-label-tertiary)" },
|
|
178
173
|
// 开关行:逐条对齐官方 SubagentModelSelectionCard.module.css 的 .toggleRow / .toggleLabel,
|
|
179
174
|
// 右侧放原生 `Switch`(同一个 ui-primitives 包),因此外观与官方卡片一致。
|
|
@@ -188,7 +183,12 @@ var S = {
|
|
|
188
183
|
},
|
|
189
184
|
toggleLabel: { flex: 1, minWidth: 0, fontSize: 13, lineHeight: 1.5 },
|
|
190
185
|
// 状态行:比说明行重一档(secondary 对 tertiary),一行说清开关当前的含义。
|
|
191
|
-
stateNote: {
|
|
186
|
+
stateNote: {
|
|
187
|
+
margin: 0,
|
|
188
|
+
fontSize: 12,
|
|
189
|
+
lineHeight: 1.5,
|
|
190
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
191
|
+
},
|
|
192
192
|
// 说明句里的外链:只用卡片既有的语义令牌,颜色取自 ui-theme 的 --dsw-alias-link。
|
|
193
193
|
// 卡片是纯内联样式、无法写 :hover,所以常驻下划线作为静态可点提示。
|
|
194
194
|
link: {
|
|
@@ -204,23 +204,15 @@ var S = {
|
|
|
204
204
|
paddingTop: 16
|
|
205
205
|
},
|
|
206
206
|
// 错误色用有定义的那个令牌:原生照抄来的那一个在 harness 里从未定义,写了不会生效(见 [AGENTS.md](./AGENTS.md))。
|
|
207
|
-
failed: {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
padding: "5px 14px",
|
|
213
|
-
font: "inherit",
|
|
214
|
-
fontSize: 13,
|
|
207
|
+
failed: {
|
|
208
|
+
flex: 1,
|
|
209
|
+
minWidth: 0,
|
|
210
|
+
margin: 0,
|
|
211
|
+
fontSize: 12,
|
|
215
212
|
lineHeight: 1.5,
|
|
216
|
-
|
|
217
|
-
background: "var(--dsw-alias-label-primary)",
|
|
218
|
-
color: "var(--dsw-alias-bg-layer-3)"
|
|
213
|
+
color: "var(--dsw-alias-state-error-primary)"
|
|
219
214
|
}
|
|
220
215
|
};
|
|
221
|
-
function dimStyle(base, disabled) {
|
|
222
|
-
return disabled ? { ...base, opacity: 0.4, cursor: "default" } : base;
|
|
223
|
-
}
|
|
224
216
|
function unrefTimer(timer) {
|
|
225
217
|
const candidate = timer;
|
|
226
218
|
if (typeof candidate === "object" && candidate !== null && "unref" in candidate && typeof candidate.unref === "function") {
|
|
@@ -268,7 +260,9 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
268
260
|
try {
|
|
269
261
|
const ops = [];
|
|
270
262
|
if (refDirty) {
|
|
271
|
-
ops.push(
|
|
263
|
+
ops.push(
|
|
264
|
+
refText === "" ? { op: "unset", path: [REF_FIELD] } : { op: "set", path: [REF_FIELD], value: refText }
|
|
265
|
+
);
|
|
272
266
|
}
|
|
273
267
|
if (hideDirty) ops.push({ op: "set", path: [HIDE_FIELD], value: hideText });
|
|
274
268
|
if (ops.length > 0) {
|
|
@@ -292,10 +286,9 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
292
286
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: S.badges, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: credential.configured ? "neutral" : "quiet", children: credential.configured ? t("secretConfigured") : t("secretMissing") }) })
|
|
293
287
|
] }),
|
|
294
288
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
295
|
-
|
|
289
|
+
import_dsh_client_ui_primitives.Input,
|
|
296
290
|
{
|
|
297
291
|
id: "zhihu-access-secret",
|
|
298
|
-
style: S.input,
|
|
299
292
|
type: "password",
|
|
300
293
|
autoComplete: "off",
|
|
301
294
|
value: secret,
|
|
@@ -307,16 +300,7 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
307
300
|
),
|
|
308
301
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: S.hint, children: [
|
|
309
302
|
t("secretHintBefore"),
|
|
310
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
311
|
-
"a",
|
|
312
|
-
{
|
|
313
|
-
style: S.link,
|
|
314
|
-
href: PROFILE_URL,
|
|
315
|
-
target: "_blank",
|
|
316
|
-
rel: "noopener noreferrer",
|
|
317
|
-
children: t("secretHintLink")
|
|
318
|
-
}
|
|
319
|
-
),
|
|
303
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { style: S.link, href: PROFILE_URL, target: "_blank", rel: "noopener noreferrer", children: t("secretHintLink") }),
|
|
320
304
|
t("secretHintAfter")
|
|
321
305
|
] }),
|
|
322
306
|
credential.writable ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: S.hint, children: t("secretShadowed") })
|
|
@@ -327,10 +311,11 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
327
311
|
refOverridden ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: S.badges, children: [
|
|
328
312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "neutral", children: t("refOverridden") }),
|
|
329
313
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
330
|
-
|
|
314
|
+
import_dsh_client_ui_primitives.Button,
|
|
331
315
|
{
|
|
332
316
|
type: "button",
|
|
333
|
-
|
|
317
|
+
variant: "ghost",
|
|
318
|
+
size: "sm",
|
|
334
319
|
disabled,
|
|
335
320
|
onClick: () => {
|
|
336
321
|
setRefDraft("");
|
|
@@ -341,10 +326,9 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
341
326
|
] }) : null
|
|
342
327
|
] }),
|
|
343
328
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
344
|
-
|
|
329
|
+
import_dsh_client_ui_primitives.Input,
|
|
345
330
|
{
|
|
346
331
|
id: "zhihu-access-secret-ref",
|
|
347
|
-
style: S.input,
|
|
348
332
|
type: "text",
|
|
349
333
|
spellCheck: false,
|
|
350
334
|
value: refText,
|
|
@@ -377,10 +361,10 @@ function ZhihuCard({ form, store, trackSavedRef, t }) {
|
|
|
377
361
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: S.footer, children: [
|
|
378
362
|
failed !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: S.failed, role: "status", children: failed }) : null,
|
|
379
363
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
380
|
-
|
|
364
|
+
import_dsh_client_ui_primitives.Button,
|
|
381
365
|
{
|
|
382
366
|
type: "button",
|
|
383
|
-
|
|
367
|
+
variant: "primary",
|
|
384
368
|
disabled: blocked,
|
|
385
369
|
onClick: () => {
|
|
386
370
|
void save();
|
|
@@ -397,7 +381,10 @@ function apply(ctx) {
|
|
|
397
381
|
const trackSavedRef = (ref) => {
|
|
398
382
|
savedRef = ref;
|
|
399
383
|
};
|
|
400
|
-
const store = createCredentialStore(
|
|
384
|
+
const store = createCredentialStore(
|
|
385
|
+
() => remote.credentials,
|
|
386
|
+
() => savedRef
|
|
387
|
+
);
|
|
401
388
|
ctx.effect(
|
|
402
389
|
() => ctx.locale.register(LOCALE_NS, ZHIHU_LOCALES),
|
|
403
390
|
"zhihu-search: card dictionaries"
|
|
@@ -438,7 +425,12 @@ function apply(ctx) {
|
|
|
438
425
|
}, "zhihu-search: configuration service probe");
|
|
439
426
|
let slotProbe;
|
|
440
427
|
ctx.effect(() => {
|
|
441
|
-
slotProbe = armProbe(
|
|
428
|
+
slotProbe = armProbe(
|
|
429
|
+
SLOT_MISSING_WARNING,
|
|
430
|
+
SLOT_LATE_INFO,
|
|
431
|
+
() => slotDeclared,
|
|
432
|
+
() => serviceDeclared
|
|
433
|
+
);
|
|
442
434
|
return () => {
|
|
443
435
|
if (slotProbe?.timer !== void 0) clearTimeout(slotProbe.timer);
|
|
444
436
|
slotProbe = void 0;
|
package/lib/index.js
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* 由返回的 disposer 释放。模块顶层**不持有任何可变状态** ——
|
|
10
10
|
* 否则 HMR 重载后会留下两代插件共用缓存与限流桶的幽灵故障。
|
|
11
11
|
*/
|
|
12
|
-
import { credentialRef, isCredentialRefName } from '@deepseek-ai/dsh-credentials';
|
|
12
|
+
import { credentialRef, isCredentialRefName, } from '@deepseek-ai/dsh-credentials';
|
|
13
13
|
import z from '@deepseek-ai/schemastery';
|
|
14
|
-
import { DEFAULT_STREAM_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, ZHIHU_BASE_URL, ZhihuClient } from './transport.js';
|
|
14
|
+
import { DEFAULT_STREAM_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, ZHIHU_BASE_URL, ZhihuClient, } from './transport.js';
|
|
15
15
|
import { resolveAccessSecret as resolveAccessSecretFrom } from './credentials.js';
|
|
16
16
|
import { migrateLegacySecret } from './migrate.js';
|
|
17
17
|
import { createState } from './state.js';
|
package/lib/present/search.js
CHANGED
|
@@ -55,7 +55,10 @@ function formatDate(seconds) {
|
|
|
55
55
|
* 不转义会把 `### [标题](url)` 撕成非法 Markdown,模型读到的结构就错位了。
|
|
56
56
|
*/
|
|
57
57
|
function escapeLinkText(input) {
|
|
58
|
-
return input
|
|
58
|
+
return input
|
|
59
|
+
.replace(/[\r\n]+/g, ' ')
|
|
60
|
+
.replace(/([[\]])/g, '\\$1')
|
|
61
|
+
.trim();
|
|
59
62
|
}
|
|
60
63
|
/**
|
|
61
64
|
* 渲染模型可见的 Markdown。
|
|
@@ -140,7 +143,11 @@ export function renderSearch(value, context = {}) {
|
|
|
140
143
|
*/
|
|
141
144
|
export function searchMetaFromValue(value) {
|
|
142
145
|
return {
|
|
143
|
-
sources: value.items.map((item) => ({
|
|
146
|
+
sources: value.items.map((item) => ({
|
|
147
|
+
url: item.url,
|
|
148
|
+
title: item.title,
|
|
149
|
+
snippet: item.snippet,
|
|
150
|
+
})),
|
|
144
151
|
truncated: value.hasMore,
|
|
145
152
|
};
|
|
146
153
|
}
|
|
@@ -167,8 +174,8 @@ export function searchMetaFromResult(meta) {
|
|
|
167
174
|
continue;
|
|
168
175
|
results.push({
|
|
169
176
|
url: raw.url,
|
|
170
|
-
...(
|
|
171
|
-
...(
|
|
177
|
+
...('title' in raw && typeof raw.title === 'string' ? { title: raw.title } : {}),
|
|
178
|
+
...('snippet' in raw && typeof raw.snippet === 'string' ? { snippet: raw.snippet } : {}),
|
|
172
179
|
});
|
|
173
180
|
}
|
|
174
181
|
return { sources: results, truncated: 'truncated' in meta && meta.truncated === true };
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
13
13
|
import { compileFilter } from '../utils/compiler.js';
|
|
14
|
-
import { presentSearchCall, presentSearchResult, renderSearch, searchMetaFromValue } from '../present/search.js';
|
|
14
|
+
import { presentSearchCall, presentSearchResult, renderSearch, searchMetaFromValue, } from '../present/search.js';
|
|
15
15
|
import { GLOBAL_SEARCH_MAX_COUNT } from '../transport.js';
|
|
16
|
-
import { executeSearch, rawRequestedCount, resolveRequestedCount, SEARCH_OUTPUT_SCHEMA } from './search-shared.js';
|
|
16
|
+
import { executeSearch, rawRequestedCount, resolveRequestedCount, SEARCH_OUTPUT_SCHEMA, } from './search-shared.js';
|
|
17
17
|
/** 工具名。 */
|
|
18
18
|
export const ZHIHU_GLOBAL_SEARCH_TOOL = 'zhihu_global_search';
|
|
19
19
|
/**
|
|
@@ -31,7 +31,14 @@ const DEFAULT_COUNT = 8;
|
|
|
31
31
|
* 未知键会被静默丢弃 —— 模型传 `page=2` 会拿到第一页却以为翻页成功。
|
|
32
32
|
* 与参数定义的一致性由 `test/tool.test.ts` 断言守着。
|
|
33
33
|
*/
|
|
34
|
-
const PARAM_NAMES = [
|
|
34
|
+
const PARAM_NAMES = [
|
|
35
|
+
'query',
|
|
36
|
+
'count',
|
|
37
|
+
'site',
|
|
38
|
+
'publishedAfter',
|
|
39
|
+
'publishedBefore',
|
|
40
|
+
'searchDb',
|
|
41
|
+
];
|
|
35
42
|
/** 协作式超时预算。 */
|
|
36
43
|
const TIMEOUT_MS = 20_000;
|
|
37
44
|
/**
|
|
@@ -50,14 +57,29 @@ export function createZhihuGlobalSearchTool(deps) {
|
|
|
50
57
|
'结果含标题、链接、摘要、作者与时间,知乎来源另带点赞数与评论数,不含图片;没有翻页参数。',
|
|
51
58
|
parameters: {
|
|
52
59
|
query: { type: 'string', required: true, description: '搜索关键词。' },
|
|
53
|
-
count: {
|
|
60
|
+
count: {
|
|
61
|
+
type: 'integer',
|
|
62
|
+
description: `返回条数,1–${String(MAX_COUNT)},默认 ${String(DEFAULT_COUNT)}。`,
|
|
63
|
+
default: DEFAULT_COUNT,
|
|
64
|
+
},
|
|
54
65
|
site: {
|
|
55
66
|
type: 'string',
|
|
56
67
|
description: '只搜索该域名,例如 github.com;传完整 URL 会被剥成主机名并去掉开头的 www.。域名是精确匹配(子站要单独写),不支持知乎域名。',
|
|
57
68
|
},
|
|
58
|
-
publishedAfter: {
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
publishedAfter: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: '只要该日期之后发布的内容,格式 YYYY-MM-DD。',
|
|
72
|
+
},
|
|
73
|
+
publishedBefore: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
description: '只要该日期之前发布的内容,格式 YYYY-MM-DD。',
|
|
76
|
+
},
|
|
77
|
+
searchDb: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
enum: ['all', 'realtime', 'static'],
|
|
80
|
+
description: '索引库,默认 all。realtime 偏最新,static 偏长期收录。',
|
|
81
|
+
default: 'all',
|
|
82
|
+
},
|
|
61
83
|
},
|
|
62
84
|
output: {
|
|
63
85
|
schema: SEARCH_OUTPUT_SCHEMA,
|
|
@@ -85,12 +107,17 @@ export function createZhihuGlobalSearchTool(deps) {
|
|
|
85
107
|
toolName: ZHIHU_GLOBAL_SEARCH_TOOL,
|
|
86
108
|
signal: exec.signal,
|
|
87
109
|
plan: (query) => {
|
|
88
|
-
const count = resolveRequestedCount(args.count, {
|
|
110
|
+
const count = resolveRequestedCount(args.count, {
|
|
111
|
+
max: MAX_COUNT,
|
|
112
|
+
fallback: DEFAULT_COUNT,
|
|
113
|
+
});
|
|
89
114
|
// 全网作用域:允许 host;编译器会拦下知乎域名并给出「请用站内搜索」的提示。
|
|
90
115
|
const filter = compileFilter({
|
|
91
116
|
...(args.site === undefined ? {} : { site: args.site }),
|
|
92
117
|
...(args.publishedAfter === undefined ? {} : { publishedAfter: args.publishedAfter }),
|
|
93
|
-
...(args.publishedBefore === undefined
|
|
118
|
+
...(args.publishedBefore === undefined
|
|
119
|
+
? {}
|
|
120
|
+
: { publishedBefore: args.publishedBefore }),
|
|
94
121
|
}, 'global');
|
|
95
122
|
const searchDb = args.searchDb ?? 'all';
|
|
96
123
|
return {
|
|
@@ -95,10 +95,16 @@ export function projectItem(item) {
|
|
|
95
95
|
// 上游没报点赞数时整个键省略,不兜底成 0 —— 写 0 等于告诉模型「没人赞」。
|
|
96
96
|
// 注意实测结论:上游**从未省略**该字段,外站网页也有这个键、值是占位的 0。
|
|
97
97
|
// 省略分支是防伪造的兜底;外站那个 0 由渲染层决定不展示(present/search.ts)。
|
|
98
|
-
...(typeof item.VoteUpCount === 'number' && Number.isFinite(item.VoteUpCount)
|
|
98
|
+
...(typeof item.VoteUpCount === 'number' && Number.isFinite(item.VoteUpCount)
|
|
99
|
+
? { voteUpCount: item.VoteUpCount }
|
|
100
|
+
: {}),
|
|
99
101
|
// 投影规则同上:上游没报就省略,绝不兜底成 0(外站那个 0 是占位值,由渲染层决定不展示)。
|
|
100
|
-
...(typeof item.CommentCount === 'number' && Number.isFinite(item.CommentCount)
|
|
101
|
-
|
|
102
|
+
...(typeof item.CommentCount === 'number' && Number.isFinite(item.CommentCount)
|
|
103
|
+
? { commentCount: item.CommentCount }
|
|
104
|
+
: {}),
|
|
105
|
+
...(typeof item.EditTime === 'number' && Number.isFinite(item.EditTime)
|
|
106
|
+
? { editTime: item.EditTime }
|
|
107
|
+
: {}),
|
|
102
108
|
// ContentType 缺失时留空,不编造标签:实测站内与网页链接的平台各自返回**空串**(字段在、值为空),
|
|
103
109
|
// 兜底成 'Answer'(站内)或 'Article'(全网)都会让模型把陌生网页当成知乎内容。
|
|
104
110
|
contentType: typeof item.ContentType === 'string' ? item.ContentType : '',
|
package/lib/tools/search.js
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
12
12
|
import { compileFilter, compileSortBy, SORT_FIELDS } from '../utils/compiler.js';
|
|
13
|
-
import { presentSearchCall, presentSearchResult, renderSearch, searchMetaFromValue } from '../present/search.js';
|
|
13
|
+
import { presentSearchCall, presentSearchResult, renderSearch, searchMetaFromValue, } from '../present/search.js';
|
|
14
14
|
import { ZHIHU_SEARCH_MAX_COUNT } from '../transport.js';
|
|
15
|
-
import { executeSearch, rawRequestedCount, resolveRequestedCount, SEARCH_OUTPUT_SCHEMA } from './search-shared.js';
|
|
15
|
+
import { executeSearch, rawRequestedCount, resolveRequestedCount, SEARCH_OUTPUT_SCHEMA, } from './search-shared.js';
|
|
16
16
|
/** 工具名。 */
|
|
17
17
|
export const ZHIHU_SEARCH_TOOL = 'zhihu_search';
|
|
18
18
|
/**
|
|
@@ -45,7 +45,9 @@ const FILTERED_CANDIDATE_COUNT = MAX_COUNT;
|
|
|
45
45
|
* @returns 条目数不超过 `requestedCount` 的结果。
|
|
46
46
|
*/
|
|
47
47
|
function sliceItems(value, requestedCount) {
|
|
48
|
-
return value.items.length <= requestedCount
|
|
48
|
+
return value.items.length <= requestedCount
|
|
49
|
+
? value
|
|
50
|
+
: { ...value, items: value.items.slice(0, requestedCount) };
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
53
|
* 参数白名单。
|
|
@@ -55,7 +57,15 @@ function sliceItems(value, requestedCount) {
|
|
|
55
57
|
* 会拿到第一页却以为翻页成功。校验放本地,schema 里不加散文。
|
|
56
58
|
* 与参数定义的一致性由 `test/tool.test.ts` 断言守着,避免两处漂移。
|
|
57
59
|
*/
|
|
58
|
-
const PARAM_NAMES = [
|
|
60
|
+
const PARAM_NAMES = [
|
|
61
|
+
'query',
|
|
62
|
+
'count',
|
|
63
|
+
'sortField',
|
|
64
|
+
'order',
|
|
65
|
+
'minValue',
|
|
66
|
+
'publishedAfter',
|
|
67
|
+
'publishedBefore',
|
|
68
|
+
];
|
|
59
69
|
/** 协作式超时预算;超时必须早于 DSH 的外层截断,才能返回结构化错误。 */
|
|
60
70
|
const TIMEOUT_MS = 15_000;
|
|
61
71
|
/**
|
|
@@ -76,7 +86,11 @@ export function createZhihuSearchTool(deps) {
|
|
|
76
86
|
// 语义化参数:模型永远不会看到 SortBy / Filter 的字符串语法。
|
|
77
87
|
parameters: {
|
|
78
88
|
query: { type: 'string', required: true, description: '搜索关键词,中文效果最好。' },
|
|
79
|
-
count: {
|
|
89
|
+
count: {
|
|
90
|
+
type: 'integer',
|
|
91
|
+
description: `返回条数,1–${String(MAX_COUNT)},默认 ${String(DEFAULT_COUNT)}。`,
|
|
92
|
+
default: DEFAULT_COUNT,
|
|
93
|
+
},
|
|
80
94
|
sortField: {
|
|
81
95
|
type: 'string',
|
|
82
96
|
enum: SORT_FIELDS,
|
|
@@ -96,8 +110,14 @@ export function createZhihuSearchTool(deps) {
|
|
|
96
110
|
type: 'number',
|
|
97
111
|
description: '[依赖 sortField] 排序字段的下限(含)。它只筛本次检索到的候选,不是全库过滤:达标项不足时返回条数会少于 count —— 放宽下限或换关键词,不要据此断定知乎没有高赞内容。',
|
|
98
112
|
},
|
|
99
|
-
publishedAfter: {
|
|
100
|
-
|
|
113
|
+
publishedAfter: {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: '只要该日期之后发布的内容,格式 YYYY-MM-DD。',
|
|
116
|
+
},
|
|
117
|
+
publishedBefore: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
description: '只要该日期之前发布的内容,格式 YYYY-MM-DD。',
|
|
120
|
+
},
|
|
101
121
|
},
|
|
102
122
|
output: {
|
|
103
123
|
schema: SEARCH_OUTPUT_SCHEMA,
|
|
@@ -106,7 +126,9 @@ export function createZhihuSearchTool(deps) {
|
|
|
106
126
|
requestedCount: rawRequestedCount(args.count, DEFAULT_COUNT),
|
|
107
127
|
minValue: args.minValue,
|
|
108
128
|
maxCount: MAX_COUNT,
|
|
109
|
-
filtered: args.minValue !== undefined ||
|
|
129
|
+
filtered: args.minValue !== undefined ||
|
|
130
|
+
args.publishedAfter !== undefined ||
|
|
131
|
+
args.publishedBefore !== undefined,
|
|
110
132
|
scope: 'zhihu',
|
|
111
133
|
}),
|
|
112
134
|
presentationMeta: (_args, value) => searchMetaFromValue(value),
|
|
@@ -124,7 +146,10 @@ export function createZhihuSearchTool(deps) {
|
|
|
124
146
|
toolName: ZHIHU_SEARCH_TOOL,
|
|
125
147
|
signal: exec.signal,
|
|
126
148
|
plan: (query) => {
|
|
127
|
-
const requestedCount = resolveRequestedCount(args.count, {
|
|
149
|
+
const requestedCount = resolveRequestedCount(args.count, {
|
|
150
|
+
max: MAX_COUNT,
|
|
151
|
+
fallback: DEFAULT_COUNT,
|
|
152
|
+
});
|
|
128
153
|
const sortField = args.sortField ?? 'default';
|
|
129
154
|
const order = args.order ?? 'desc';
|
|
130
155
|
const minValue = args.minValue;
|
|
@@ -136,15 +161,24 @@ export function createZhihuSearchTool(deps) {
|
|
|
136
161
|
// 站内搜索作用域:只允许 publish_time,site 会被编译器拒绝。
|
|
137
162
|
const filter = compileFilter({
|
|
138
163
|
...(args.publishedAfter === undefined ? {} : { publishedAfter: args.publishedAfter }),
|
|
139
|
-
...(args.publishedBefore === undefined
|
|
164
|
+
...(args.publishedBefore === undefined
|
|
165
|
+
? {}
|
|
166
|
+
: { publishedBefore: args.publishedBefore }),
|
|
140
167
|
}, 'zhihu');
|
|
141
168
|
// 有下限时把候选池取满(理由见 FILTERED_CANDIDATE_COUNT)。
|
|
142
|
-
const poolCount = minValue === undefined
|
|
169
|
+
const poolCount = minValue === undefined
|
|
170
|
+
? requestedCount
|
|
171
|
+
: Math.max(requestedCount, FILTERED_CANDIDATE_COUNT);
|
|
143
172
|
// 缓存键必须用**归一化后**的参数,且必须用候选池大小:
|
|
144
173
|
// 否则 count=3 与 count=10 会各占一个键,却发出两个内容相同的请求。
|
|
145
174
|
return {
|
|
146
175
|
cacheArgs: { query, count: poolCount, sortBy, filter },
|
|
147
|
-
fetch: (signal) => deps.client.searchZhihu({
|
|
176
|
+
fetch: (signal) => deps.client.searchZhihu({
|
|
177
|
+
query,
|
|
178
|
+
count: poolCount,
|
|
179
|
+
...(sortBy === undefined ? {} : { sortBy }),
|
|
180
|
+
...(filter === undefined ? {} : { filter }),
|
|
181
|
+
}, signal),
|
|
148
182
|
// 缓存完整池子,返回按本次条数截断 —— 顺序不可颠倒。
|
|
149
183
|
onReturn: (value) => sliceItems(value, requestedCount),
|
|
150
184
|
};
|
package/lib/tools/zhida.js
CHANGED
|
@@ -45,7 +45,11 @@ export function createZhihuZhidaTool(deps) {
|
|
|
45
45
|
'与两个搜索工具的区别:搜索返回可点开的来源列表,直答返回一段成体系的回答——要来源用搜索,要解释用直答。' +
|
|
46
46
|
'答案由知乎生成,可能有误,重要结论请自行核对。',
|
|
47
47
|
parameters: {
|
|
48
|
-
question: {
|
|
48
|
+
question: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
required: true,
|
|
51
|
+
description: '要提问的问题,中文描述越具体越好。',
|
|
52
|
+
},
|
|
49
53
|
mode: {
|
|
50
54
|
type: 'string',
|
|
51
55
|
enum: ZHIDA_MODELS,
|
|
@@ -125,7 +129,14 @@ export function createZhihuZhidaTool(deps) {
|
|
|
125
129
|
return { ...stored, reasoning: includeReasoning ? stored.reasoning : '' };
|
|
126
130
|
}
|
|
127
131
|
catch (error) {
|
|
128
|
-
return {
|
|
132
|
+
return {
|
|
133
|
+
ok: false,
|
|
134
|
+
question,
|
|
135
|
+
model: model ?? '',
|
|
136
|
+
answer: '',
|
|
137
|
+
reasoning: '',
|
|
138
|
+
error: mapError(error),
|
|
139
|
+
};
|
|
129
140
|
}
|
|
130
141
|
},
|
|
131
142
|
});
|
package/lib/transport.js
CHANGED
|
@@ -98,10 +98,7 @@ function mapPlatformError(code, message) {
|
|
|
98
98
|
}
|
|
99
99
|
/** 判断异常是否为 AbortSignal 触发的中断。 */
|
|
100
100
|
function isAbortError(error) {
|
|
101
|
-
return (typeof error === 'object' &&
|
|
102
|
-
error !== null &&
|
|
103
|
-
'name' in error &&
|
|
104
|
-
error.name === 'AbortError');
|
|
101
|
+
return (typeof error === 'object' && error !== null && 'name' in error && error.name === 'AbortError');
|
|
105
102
|
}
|
|
106
103
|
/** 把任意异常归一化为 {@link ZhihuClientError},保留取消语义。 */
|
|
107
104
|
function toClientError(error, signal) {
|
|
@@ -161,17 +158,15 @@ function sleep(ms, signal) {
|
|
|
161
158
|
reject(new ZhihuClientError('aborted', '请求已被取消。'));
|
|
162
159
|
return;
|
|
163
160
|
}
|
|
164
|
-
|
|
161
|
+
const timer = setTimeout(() => {
|
|
162
|
+
signal?.removeEventListener('abort', onAbort);
|
|
163
|
+
resolve();
|
|
164
|
+
}, ms);
|
|
165
165
|
const onAbort = () => {
|
|
166
|
-
|
|
167
|
-
clearTimeout(timer);
|
|
166
|
+
clearTimeout(timer);
|
|
168
167
|
signal?.removeEventListener('abort', onAbort);
|
|
169
168
|
reject(new ZhihuClientError('aborted', '请求已被取消。'));
|
|
170
169
|
};
|
|
171
|
-
timer = setTimeout(() => {
|
|
172
|
-
signal?.removeEventListener('abort', onAbort);
|
|
173
|
-
resolve();
|
|
174
|
-
}, ms);
|
|
175
170
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
176
171
|
});
|
|
177
172
|
}
|
|
@@ -305,7 +300,9 @@ export function classifyChatFailure(failure, status) {
|
|
|
305
300
|
hint: '知乎直答触发频率限制。稍等片刻再试,或降低调用频率。',
|
|
306
301
|
});
|
|
307
302
|
}
|
|
308
|
-
if (status === 401 ||
|
|
303
|
+
if (status === 401 ||
|
|
304
|
+
status === 403 ||
|
|
305
|
+
/unauthor|authentication|forbidden|invalid.?api.?key|20001/.test(hay)) {
|
|
309
306
|
return new ZhihuClientError('auth', message, {
|
|
310
307
|
...codeField,
|
|
311
308
|
hint: '鉴权失败。若 Secret 正确,请检查本机系统时间(知乎要求时间差 < 10 分钟)。',
|
|
@@ -319,7 +316,8 @@ export function classifyChatFailure(failure, status) {
|
|
|
319
316
|
hint: '请求不被知乎直答接受。若与档位有关,换成 fast 或 thinking 再试;档位是否可用取决于账号授权。',
|
|
320
317
|
});
|
|
321
318
|
}
|
|
322
|
-
if ((status ?? 0) >= 500 ||
|
|
319
|
+
if ((status ?? 0) >= 500 ||
|
|
320
|
+
/server_error|internal|overload|unavailable|temporar|90001/.test(hay)) {
|
|
323
321
|
return new ZhihuClientError('server', message, {
|
|
324
322
|
...codeField,
|
|
325
323
|
hint: '知乎服务端错误,请稍后重试。',
|
|
@@ -372,10 +370,14 @@ export function deltaFromPayload(payload) {
|
|
|
372
370
|
: undefined);
|
|
373
371
|
const chunk = {};
|
|
374
372
|
if (typeof delta === 'object' && delta !== null) {
|
|
375
|
-
const content = 'content' in delta && typeof delta.content === 'string' && delta.content !== ''
|
|
373
|
+
const content = 'content' in delta && typeof delta.content === 'string' && delta.content !== ''
|
|
374
|
+
? delta.content
|
|
375
|
+
: undefined;
|
|
376
376
|
if (content !== undefined)
|
|
377
377
|
chunk.content = content;
|
|
378
|
-
const reasoning = 'reasoning_content' in delta &&
|
|
378
|
+
const reasoning = 'reasoning_content' in delta &&
|
|
379
|
+
typeof delta.reasoning_content === 'string' &&
|
|
380
|
+
delta.reasoning_content !== ''
|
|
379
381
|
? delta.reasoning_content
|
|
380
382
|
: undefined;
|
|
381
383
|
if (reasoning !== undefined)
|
|
@@ -392,7 +394,7 @@ function isEnvelope(value) {
|
|
|
392
394
|
if (typeof value !== 'object' || value === null)
|
|
393
395
|
return false;
|
|
394
396
|
const record = value;
|
|
395
|
-
return typeof record['Code'] === 'number' && typeof record['Message'] === 'string' && 'Data' in record;
|
|
397
|
+
return (typeof record['Code'] === 'number' && typeof record['Message'] === 'string' && 'Data' in record);
|
|
396
398
|
}
|
|
397
399
|
/**
|
|
398
400
|
* 知乎开放平台客户端。
|
|
@@ -541,7 +543,11 @@ export class ZhihuClient {
|
|
|
541
543
|
*/
|
|
542
544
|
async searchZhihu(request, signal) {
|
|
543
545
|
const data = await this.#requestJson(this.#searchPath(ENDPOINT_ZHIHU_SEARCH, request, ZHIHU_SEARCH_MAX_COUNT), { method: 'GET' }, signal, 1);
|
|
544
|
-
return {
|
|
546
|
+
return {
|
|
547
|
+
HasMore: data?.HasMore ?? false,
|
|
548
|
+
Items: data?.Items ?? [],
|
|
549
|
+
SearchHashId: data?.SearchHashId,
|
|
550
|
+
};
|
|
545
551
|
}
|
|
546
552
|
/**
|
|
547
553
|
* 知乎全网搜索。
|
|
@@ -551,7 +557,11 @@ export class ZhihuClient {
|
|
|
551
557
|
*/
|
|
552
558
|
async searchGlobal(request, signal) {
|
|
553
559
|
const data = await this.#requestJson(this.#searchPath(ENDPOINT_GLOBAL_SEARCH, request, GLOBAL_SEARCH_MAX_COUNT), { method: 'GET' }, signal, 1);
|
|
554
|
-
return {
|
|
560
|
+
return {
|
|
561
|
+
HasMore: data?.HasMore ?? false,
|
|
562
|
+
Items: data?.Items ?? [],
|
|
563
|
+
SearchHashId: data?.SearchHashId,
|
|
564
|
+
};
|
|
555
565
|
}
|
|
556
566
|
/** 查询每日额度;实测不消耗业务额度,可用于自检。 */
|
|
557
567
|
async quota(signal) {
|
|
@@ -632,7 +642,9 @@ export class ZhihuClient {
|
|
|
632
642
|
catch {
|
|
633
643
|
// 落到下面的通用分支。
|
|
634
644
|
}
|
|
635
|
-
return new ZhihuClientError('parse', `知乎直答未返回事件流(HTTP ${status})。`, {
|
|
645
|
+
return new ZhihuClientError('parse', `知乎直答未返回事件流(HTTP ${status})。`, {
|
|
646
|
+
hint: text.slice(0, 200),
|
|
647
|
+
});
|
|
636
648
|
}
|
|
637
649
|
/**
|
|
638
650
|
* 执行一次直答并拼接完整回答。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* 挂载点是插件管理页声明的 `plugins.bundle.config` 槽,key 是**包名**。
|
|
6
6
|
* 这个槽**只渲染 `view: 'page'`,且座位里没有任何 `form`**(DSH `slot-contract.ts:12-16`
|
|
7
|
-
* 「Bundle configuration renders only `page`」;`PluginManagerPage.tsx:
|
|
7
|
+
* 「Bundle configuration renders only `page`」;`PluginManagerPage.tsx:579` 只递 `view` 与
|
|
8
8
|
* `entryKey`)—— 表单因此由卡片自己向 `ctx.configForms.get(<loader entry id>)` 取,
|
|
9
9
|
* 这也是该槽唯一的官方取表单路径。
|
|
10
10
|
*
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
* 与官方 web 搜索卡片同一套做法。配置里只留引用名,因此活动 profile 的 Cordis patch
|
|
29
29
|
* 被截图或上传时不泄任何凭据。
|
|
30
30
|
*
|
|
31
|
-
* 复用 `@deepseek-ai/dsh-client-ui-primitives` 的 `
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* 复用 `@deepseek-ai/dsh-client-ui-primitives` 的 `Input`、`Button`、`Switch` 与 `Tag`:
|
|
32
|
+
* 那是公共基础库,不是别的插件 —— 被 bundle-purity gate 禁止的是跨插件值导入。
|
|
33
|
+
* 行布局(label / badge / hint 的排布)仍是内联样式,取值只用 `--dsw-alias-*` 语义令牌。
|
|
34
34
|
*/
|
|
35
35
|
import type { Context } from '@deepseek-ai/cordis';
|
|
36
36
|
/**
|
package/lib/utils/text.js
CHANGED
|
@@ -68,6 +68,8 @@ export function stripTrackingParams(input) {
|
|
|
68
68
|
for (const key of keys)
|
|
69
69
|
parsed.searchParams.delete(key);
|
|
70
70
|
// 参数被清空后会留下一个孤立的 '?',Markdown 链接里很难看。
|
|
71
|
-
return parsed.search === '' && input.includes('?')
|
|
71
|
+
return parsed.search === '' && input.includes('?')
|
|
72
|
+
? `${parsed.origin}${parsed.pathname}${parsed.hash}`
|
|
73
|
+
: parsed.toString();
|
|
72
74
|
}
|
|
73
75
|
//# sourceMappingURL=text.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-zhihu-search",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Zhihu in-site search, global web search, and Zhida answers for the model, over the official Zhihu Open Platform API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
],
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=20",
|
|
51
|
-
"dsh": ">=0.1.7-alpha.1 <0.
|
|
51
|
+
"dsh": ">=0.1.7-alpha.1 <0.3.0"
|
|
52
52
|
},
|
|
53
53
|
"dsh": {
|
|
54
54
|
"bundle": {
|
|
@@ -67,20 +67,23 @@
|
|
|
67
67
|
"test": "npm run build && vitest run",
|
|
68
68
|
"test:watch": "vitest",
|
|
69
69
|
"test:contract": "vitest run --config vitest.contract.config.ts",
|
|
70
|
+
"lint": "eslint .",
|
|
71
|
+
"format": "prettier --write .",
|
|
72
|
+
"format:check": "prettier --check .",
|
|
70
73
|
"check:release": "node scripts/check-release.mjs",
|
|
71
74
|
"prepare": "npm run build"
|
|
72
75
|
},
|
|
73
76
|
"peerDependencies": {
|
|
74
77
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
75
|
-
"@deepseek-ai/dsh-client-locale": ">=0.1.7-alpha.1 <0.
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-alpha.1 <0.
|
|
77
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-alpha.1 <0.
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-alpha.1 <0.
|
|
79
|
-
"@deepseek-ai/dsh-credentials": ">=0.1.7-alpha.1 <0.
|
|
80
|
-
"@deepseek-ai/dsh-llm": ">=0.1.7-alpha.1 <0.
|
|
81
|
-
"@deepseek-ai/dsh-settings": ">=0.1.7-alpha.1 <0.
|
|
82
|
-
"@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1 <0.
|
|
83
|
-
"@deepseek-ai/dsh-util-values": ">=0.1.7-alpha.1 <0.
|
|
78
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.7-alpha.1 <0.3.0",
|
|
79
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-alpha.1 <0.3.0",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-alpha.1 <0.3.0",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-alpha.1 <0.3.0",
|
|
82
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.7-alpha.1 <0.3.0",
|
|
83
|
+
"@deepseek-ai/dsh-llm": ">=0.1.7-alpha.1 <0.3.0",
|
|
84
|
+
"@deepseek-ai/dsh-settings": ">=0.1.7-alpha.1 <0.3.0",
|
|
85
|
+
"@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1 <0.3.0",
|
|
86
|
+
"@deepseek-ai/dsh-util-values": ">=0.1.7-alpha.1 <0.3.0",
|
|
84
87
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
85
88
|
"react": "^18.3.1",
|
|
86
89
|
"react-dom": "^18.3.1"
|
|
@@ -88,32 +91,38 @@
|
|
|
88
91
|
"devDependencies": {
|
|
89
92
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
90
93
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.4",
|
|
91
|
-
"@deepseek-ai/dsh-agent": ">=0.1.7-alpha.1 <0.
|
|
92
|
-
"@deepseek-ai/dsh-client-locale": ">=0.1.7-alpha.1 <0.
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.1.7-alpha.1 <0.
|
|
94
|
-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-alpha.1 <0.
|
|
95
|
-
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.7-alpha.1 <0.
|
|
96
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-alpha.1 <0.
|
|
97
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-alpha.1 <0.
|
|
98
|
-
"@deepseek-ai/dsh-credentials": ">=0.1.7-alpha.1 <0.
|
|
99
|
-
"@deepseek-ai/dsh-invariants": ">=0.1.7-alpha.1 <0.
|
|
100
|
-
"@deepseek-ai/dsh-llm": ">=0.1.7-alpha.1 <0.
|
|
101
|
-
"@deepseek-ai/dsh-scope": ">=0.1.7-alpha.1 <0.
|
|
102
|
-
"@deepseek-ai/dsh-session": ">=0.1.7-alpha.1 <0.
|
|
103
|
-
"@deepseek-ai/dsh-session-projection": ">=0.1.7-alpha.1 <0.
|
|
104
|
-
"@deepseek-ai/dsh-settings": ">=0.1.7-alpha.1 <0.
|
|
105
|
-
"@deepseek-ai/dsh-system-prompt": ">=0.1.7-alpha.1 <0.
|
|
106
|
-
"@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1 <0.
|
|
107
|
-
"@deepseek-ai/dsh-user-approval": ">=0.1.7-alpha.1 <0.
|
|
108
|
-
"@deepseek-ai/dsh-util-values": ">=0.1.7-alpha.1 <0.
|
|
94
|
+
"@deepseek-ai/dsh-agent": ">=0.1.7-alpha.1 <0.3.0",
|
|
95
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.7-alpha.1 <0.3.0",
|
|
96
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.1.7-alpha.1 <0.3.0",
|
|
97
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-alpha.1 <0.3.0",
|
|
98
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.7-alpha.1 <0.3.0",
|
|
99
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-alpha.1 <0.3.0",
|
|
100
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-alpha.1 <0.3.0",
|
|
101
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.7-alpha.1 <0.3.0",
|
|
102
|
+
"@deepseek-ai/dsh-invariants": ">=0.1.7-alpha.1 <0.3.0",
|
|
103
|
+
"@deepseek-ai/dsh-llm": ">=0.1.7-alpha.1 <0.3.0",
|
|
104
|
+
"@deepseek-ai/dsh-scope": ">=0.1.7-alpha.1 <0.3.0",
|
|
105
|
+
"@deepseek-ai/dsh-session": ">=0.1.7-alpha.1 <0.3.0",
|
|
106
|
+
"@deepseek-ai/dsh-session-projection": ">=0.1.7-alpha.1 <0.3.0",
|
|
107
|
+
"@deepseek-ai/dsh-settings": ">=0.1.7-alpha.1 <0.3.0",
|
|
108
|
+
"@deepseek-ai/dsh-system-prompt": ">=0.1.7-alpha.1 <0.3.0",
|
|
109
|
+
"@deepseek-ai/dsh-tools": ">=0.1.7-alpha.1 <0.3.0",
|
|
110
|
+
"@deepseek-ai/dsh-user-approval": ">=0.1.7-alpha.1 <0.3.0",
|
|
111
|
+
"@deepseek-ai/dsh-util-values": ">=0.1.7-alpha.1 <0.3.0",
|
|
109
112
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
113
|
+
"@eslint/js": "^10.0.1",
|
|
110
114
|
"@types/node": "^20.0.0",
|
|
111
115
|
"@types/react": "~18.3.1",
|
|
112
116
|
"@types/react-dom": "~18.3.1",
|
|
113
117
|
"esbuild": "^0.21.5",
|
|
118
|
+
"eslint": "^10.11.0",
|
|
119
|
+
"eslint-config-prettier": "^10.1.8",
|
|
120
|
+
"globals": "^17.12.0",
|
|
121
|
+
"prettier": "^3.9.9",
|
|
114
122
|
"react": "^18.3.1",
|
|
115
123
|
"react-dom": "^18.3.1",
|
|
116
124
|
"typescript": "^5.4.0",
|
|
125
|
+
"typescript-eslint": "^8.70.1",
|
|
117
126
|
"vitest": "^2.0.0"
|
|
118
127
|
}
|
|
119
128
|
}
|