@klarkxy/dsh-zhihu 0.2.11 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -9
- package/docs/README.zh-CN.md +3 -9
- package/lib/client.js +10 -4
- package/lib/contracts.d.ts +5 -13
- package/lib/contracts.js +5 -13
- package/lib/contracts.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/open-platform.js +3 -9
- package/lib/open-platform.js.map +1 -1
- package/lib/tools.js +165 -578
- package/lib/tools.js.map +1 -1
- package/package.json +8 -8
package/lib/tools.js
CHANGED
|
@@ -1,396 +1,93 @@
|
|
|
1
|
-
import { _ as executeZhihuSearch, a as ZHIHU_ASK_DEFAULT_MODEL, c as executeZhihuAsk, d as executeZhihuKnowledgeSearch, f as normalizeRecallScopes, g as renderZhihuKnowledgeSearch, h as renderZhihuHotList, i as zhihuOpenPlatformResultCount, l as executeZhihuGlobalSearch, m as renderZhihuGlobalSearch, n as executeZhihuOpenPlatform, o as ZHIHU_ASK_MODELS, p as renderZhihuAsk, s as ZHIHU_RECALL_SCOPES, t as ZHIHU_OPEN_PLATFORM_APIS, u as executeZhihuHotList, v as renderZhihuSearch, x as reportExecuted } from "./open-platform.js";
|
|
2
|
-
import {
|
|
1
|
+
import { _ as executeZhihuSearch, a as ZHIHU_ASK_DEFAULT_MODEL, c as executeZhihuAsk, d as executeZhihuKnowledgeSearch, f as normalizeRecallScopes, g as renderZhihuKnowledgeSearch, h as renderZhihuHotList, i as zhihuOpenPlatformResultCount, l as executeZhihuGlobalSearch, m as renderZhihuGlobalSearch, n as executeZhihuOpenPlatform, o as ZHIHU_ASK_MODELS, p as renderZhihuAsk, s as ZHIHU_RECALL_SCOPES, t as ZHIHU_OPEN_PLATFORM_APIS, u as executeZhihuHotList, v as renderZhihuSearch, x as reportExecuted, y as ZhihuSearchError } from "./open-platform.js";
|
|
2
|
+
import { ZHIHU_ACCOUNT_TOOL_NAME, ZHIHU_QUOTA_IDS, ZHIHU_RESEARCH_TOOL_NAME } from "./contracts.js";
|
|
3
3
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
4
4
|
//#region src/tool-definitions.ts
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
comments: {
|
|
30
|
-
type: "integer",
|
|
31
|
-
required: true
|
|
32
|
-
},
|
|
33
|
-
author: {
|
|
34
|
-
type: "string",
|
|
35
|
-
required: true
|
|
36
|
-
},
|
|
37
|
-
authority: {
|
|
38
|
-
type: "string",
|
|
39
|
-
required: true
|
|
40
|
-
},
|
|
41
|
-
editTime: {
|
|
42
|
-
type: "string",
|
|
43
|
-
required: true
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
function createZhihuSearchTool(options = {}) {
|
|
48
|
-
const { onExecuted, ...client } = options;
|
|
49
|
-
return defineTool({
|
|
50
|
-
name: ZHIHU_SEARCH_TOOL_NAME,
|
|
51
|
-
description: "知乎站内搜索(GET /api/v1/content/zhihu_search),取社区证据;仅作社区/读者反馈参考,不构成 canon,不写入项目文件。",
|
|
52
|
-
parameters: {
|
|
53
|
-
query: {
|
|
54
|
-
type: "string",
|
|
55
|
-
required: true,
|
|
56
|
-
description: "搜索词,2-100 字符。"
|
|
57
|
-
},
|
|
58
|
-
count: {
|
|
59
|
-
type: "integer",
|
|
60
|
-
description: `返回条数,1-10,默认 5。`
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
output: {
|
|
64
|
-
schema: {
|
|
65
|
-
type: "object",
|
|
66
|
-
additionalProperties: false,
|
|
67
|
-
properties: {
|
|
68
|
-
version: {
|
|
69
|
-
type: "integer",
|
|
70
|
-
required: true
|
|
71
|
-
},
|
|
72
|
-
query: {
|
|
73
|
-
type: "string",
|
|
74
|
-
required: true
|
|
75
|
-
},
|
|
76
|
-
count: {
|
|
77
|
-
type: "integer",
|
|
78
|
-
required: true
|
|
79
|
-
},
|
|
80
|
-
items: {
|
|
81
|
-
type: "array",
|
|
82
|
-
required: true,
|
|
83
|
-
items: SEARCH_ITEM_SCHEMA
|
|
84
|
-
},
|
|
85
|
-
emptyReason: { type: "string" }
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
render(_args, value) {
|
|
89
|
-
return [{
|
|
90
|
-
type: "text",
|
|
91
|
-
text: renderZhihuSearch(value)
|
|
92
|
-
}];
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
isConcurrencySafe() {
|
|
96
|
-
return true;
|
|
97
|
-
},
|
|
98
|
-
async execute(args, exec) {
|
|
99
|
-
const typed = args;
|
|
100
|
-
try {
|
|
101
|
-
const result = await executeZhihuSearch(typed.query, typed.count ?? 5, {
|
|
102
|
-
...client,
|
|
103
|
-
signal: exec.signal
|
|
104
|
-
});
|
|
105
|
-
reportExecuted(onExecuted, {
|
|
106
|
-
ok: true,
|
|
107
|
-
results: result.items.length
|
|
108
|
-
});
|
|
109
|
-
return result;
|
|
110
|
-
} catch (error) {
|
|
111
|
-
reportExecuted(onExecuted, {
|
|
112
|
-
ok: false,
|
|
113
|
-
results: 0
|
|
114
|
-
});
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
const OTHER_SEARCH_ITEM_SCHEMA = {
|
|
121
|
-
type: "object",
|
|
122
|
-
additionalProperties: false,
|
|
123
|
-
properties: {
|
|
124
|
-
title: {
|
|
125
|
-
type: "string",
|
|
126
|
-
required: true
|
|
127
|
-
},
|
|
128
|
-
type: {
|
|
129
|
-
type: "string",
|
|
130
|
-
required: true
|
|
131
|
-
},
|
|
132
|
-
url: {
|
|
133
|
-
type: "string",
|
|
134
|
-
required: true
|
|
135
|
-
},
|
|
136
|
-
summary: {
|
|
137
|
-
type: "string",
|
|
138
|
-
required: true
|
|
139
|
-
},
|
|
140
|
-
votes: {
|
|
141
|
-
type: "integer",
|
|
142
|
-
required: true
|
|
143
|
-
},
|
|
144
|
-
comments: {
|
|
145
|
-
type: "integer",
|
|
146
|
-
required: true
|
|
147
|
-
},
|
|
148
|
-
author: {
|
|
149
|
-
type: "string",
|
|
150
|
-
required: true
|
|
151
|
-
},
|
|
152
|
-
authority: {
|
|
153
|
-
type: "string",
|
|
154
|
-
required: true
|
|
155
|
-
},
|
|
156
|
-
editTime: {
|
|
157
|
-
type: "string",
|
|
158
|
-
required: true
|
|
159
|
-
}
|
|
5
|
+
const ZHIHU_RESEARCH_ACTIONS = [
|
|
6
|
+
"search",
|
|
7
|
+
"global_search",
|
|
8
|
+
"hot_list",
|
|
9
|
+
"ask",
|
|
10
|
+
"knowledge_search"
|
|
11
|
+
];
|
|
12
|
+
/** 合并前的五个检索工具各自执行逻辑不变,这里只按 action 分发。 */
|
|
13
|
+
function executeResearch(action, args, client, signal) {
|
|
14
|
+
const options = {
|
|
15
|
+
...client,
|
|
16
|
+
signal
|
|
17
|
+
};
|
|
18
|
+
if (action === "search") return executeZhihuSearch(args.query, args.count ?? 5, options).then((result) => ({
|
|
19
|
+
result,
|
|
20
|
+
results: result.items.length
|
|
21
|
+
}));
|
|
22
|
+
if (action === "global_search") {
|
|
23
|
+
const searchDb = args.searchDb === "realtime" || args.searchDb === "static" ? args.searchDb : "all";
|
|
24
|
+
return executeZhihuGlobalSearch(args.query, args.count ?? 10, searchDb, options).then((result) => ({
|
|
25
|
+
result,
|
|
26
|
+
results: result.items.length
|
|
27
|
+
}));
|
|
160
28
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
} catch (error) {
|
|
172
|
-
reportExecuted(onExecuted, {
|
|
173
|
-
ok: false,
|
|
174
|
-
results: 0
|
|
175
|
-
});
|
|
176
|
-
throw error;
|
|
29
|
+
if (action === "hot_list") return executeZhihuHotList(args.limit ?? 10, options).then((result) => ({
|
|
30
|
+
result,
|
|
31
|
+
results: result.items.length
|
|
32
|
+
}));
|
|
33
|
+
if (action === "ask") {
|
|
34
|
+
const model = ZHIHU_ASK_MODELS.includes(args.model ?? "") ? args.model : ZHIHU_ASK_DEFAULT_MODEL;
|
|
35
|
+
return executeZhihuAsk(args.query, model, options).then((result) => ({
|
|
36
|
+
result,
|
|
37
|
+
results: result.content ? 1 : 0
|
|
38
|
+
}));
|
|
177
39
|
}
|
|
40
|
+
return executeZhihuKnowledgeSearch(args.query, args.limit ?? 5, normalizeRecallScopes(args.recallScopes), options).then((result) => ({
|
|
41
|
+
result,
|
|
42
|
+
results: result.items.length
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
function renderResearch(action, value) {
|
|
46
|
+
if (action === "search") return renderZhihuSearch(value);
|
|
47
|
+
if (action === "global_search") return renderZhihuGlobalSearch(value);
|
|
48
|
+
if (action === "hot_list") return renderZhihuHotList(value);
|
|
49
|
+
if (action === "ask") return renderZhihuAsk(value);
|
|
50
|
+
return renderZhihuKnowledgeSearch(value);
|
|
178
51
|
}
|
|
179
|
-
function
|
|
52
|
+
function createZhihuResearchTool(options = {}) {
|
|
180
53
|
const { onExecuted, ...client } = options;
|
|
181
54
|
return defineTool({
|
|
182
|
-
name:
|
|
183
|
-
description: "
|
|
55
|
+
name: ZHIHU_RESEARCH_TOOL_NAME,
|
|
56
|
+
description: "知乎调研检索与问答,结果仅作社区参考,不构成 canon,不写入项目文件。action:search 站内;global_search 站外;hot_list 热榜;ask 直答;knowledge_search 知识库。",
|
|
184
57
|
parameters: {
|
|
58
|
+
action: {
|
|
59
|
+
type: "string",
|
|
60
|
+
enum: ZHIHU_RESEARCH_ACTIONS,
|
|
61
|
+
required: true
|
|
62
|
+
},
|
|
185
63
|
query: {
|
|
186
64
|
type: "string",
|
|
187
|
-
|
|
188
|
-
description: "搜索词,2-100 字符。"
|
|
65
|
+
description: "检索词,2-100 字符;除 hot_list 外必填。"
|
|
189
66
|
},
|
|
190
67
|
count: {
|
|
191
68
|
type: "integer",
|
|
192
|
-
description:
|
|
69
|
+
description: `search 1-10(默认 5)、global_search 1-20(默认 10)。`
|
|
193
70
|
},
|
|
194
|
-
|
|
195
|
-
type: "
|
|
196
|
-
description:
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
output: {
|
|
200
|
-
schema: {
|
|
201
|
-
type: "object",
|
|
202
|
-
additionalProperties: false,
|
|
203
|
-
properties: {
|
|
204
|
-
version: {
|
|
205
|
-
type: "integer",
|
|
206
|
-
required: true
|
|
207
|
-
},
|
|
208
|
-
query: {
|
|
209
|
-
type: "string",
|
|
210
|
-
required: true
|
|
211
|
-
},
|
|
212
|
-
count: {
|
|
213
|
-
type: "integer",
|
|
214
|
-
required: true
|
|
215
|
-
},
|
|
216
|
-
searchDb: {
|
|
217
|
-
type: "string",
|
|
218
|
-
required: true
|
|
219
|
-
},
|
|
220
|
-
items: {
|
|
221
|
-
type: "array",
|
|
222
|
-
required: true,
|
|
223
|
-
items: OTHER_SEARCH_ITEM_SCHEMA
|
|
224
|
-
},
|
|
225
|
-
emptyReason: { type: "string" }
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
render(_args, value) {
|
|
229
|
-
return [{
|
|
230
|
-
type: "text",
|
|
231
|
-
text: renderZhihuGlobalSearch(value)
|
|
232
|
-
}];
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
isConcurrencySafe() {
|
|
236
|
-
return true;
|
|
237
|
-
},
|
|
238
|
-
async execute(args, exec) {
|
|
239
|
-
const typed = args;
|
|
240
|
-
const searchDb = typed.searchDb === "realtime" || typed.searchDb === "static" ? typed.searchDb : "all";
|
|
241
|
-
return await metered(onExecuted, () => executeZhihuGlobalSearch(typed.query, typed.count ?? 10, searchDb, {
|
|
242
|
-
...client,
|
|
243
|
-
signal: exec.signal
|
|
244
|
-
}), (result) => result.items.length);
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
function createZhihuHotListTool(options = {}) {
|
|
249
|
-
const { onExecuted, ...client } = options;
|
|
250
|
-
return defineTool({
|
|
251
|
-
name: ZHIHU_HOT_LIST_TOOL_NAME,
|
|
252
|
-
description: "知乎热榜(GET /api/v1/content/hot_list),了解当前社区热点;仅作题材参考,不构成 canon,不写入项目文件。",
|
|
253
|
-
parameters: { limit: {
|
|
254
|
-
type: "integer",
|
|
255
|
-
description: `返回条数,1-30,默认 10。`
|
|
256
|
-
} },
|
|
257
|
-
output: {
|
|
258
|
-
schema: {
|
|
259
|
-
type: "object",
|
|
260
|
-
additionalProperties: false,
|
|
261
|
-
properties: {
|
|
262
|
-
version: {
|
|
263
|
-
type: "integer",
|
|
264
|
-
required: true
|
|
265
|
-
},
|
|
266
|
-
limit: {
|
|
267
|
-
type: "integer",
|
|
268
|
-
required: true
|
|
269
|
-
},
|
|
270
|
-
items: {
|
|
271
|
-
type: "array",
|
|
272
|
-
required: true,
|
|
273
|
-
items: {
|
|
274
|
-
type: "object",
|
|
275
|
-
additionalProperties: false,
|
|
276
|
-
properties: {
|
|
277
|
-
title: {
|
|
278
|
-
type: "string",
|
|
279
|
-
required: true
|
|
280
|
-
},
|
|
281
|
-
url: {
|
|
282
|
-
type: "string",
|
|
283
|
-
required: true
|
|
284
|
-
},
|
|
285
|
-
summary: {
|
|
286
|
-
type: "string",
|
|
287
|
-
required: true
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
71
|
+
limit: {
|
|
72
|
+
type: "integer",
|
|
73
|
+
description: `hot_list 1-30(默认 10)、knowledge_search 1-10(默认 5)。`
|
|
293
74
|
},
|
|
294
|
-
|
|
295
|
-
return [{
|
|
296
|
-
type: "text",
|
|
297
|
-
text: renderZhihuHotList(value)
|
|
298
|
-
}];
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
isConcurrencySafe() {
|
|
302
|
-
return true;
|
|
303
|
-
},
|
|
304
|
-
async execute(args, exec) {
|
|
305
|
-
const typed = args;
|
|
306
|
-
return await metered(onExecuted, () => executeZhihuHotList(typed.limit ?? 10, {
|
|
307
|
-
...client,
|
|
308
|
-
signal: exec.signal
|
|
309
|
-
}), (result) => result.items.length);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
function createZhihuAskTool(options = {}) {
|
|
314
|
-
const { onExecuted, ...client } = options;
|
|
315
|
-
return defineTool({
|
|
316
|
-
name: ZHIHU_ASK_TOOL_NAME,
|
|
317
|
-
description: "知乎直答(POST /v1/chat/completions,OpenAI 兼容),基于社区内容生成综合回答,适合考据与背景调研;仅作参考,不构成 canon,不写入项目文件。",
|
|
318
|
-
parameters: {
|
|
319
|
-
query: {
|
|
75
|
+
searchDb: {
|
|
320
76
|
type: "string",
|
|
321
|
-
|
|
322
|
-
|
|
77
|
+
enum: [
|
|
78
|
+
"all",
|
|
79
|
+
"realtime",
|
|
80
|
+
"static"
|
|
81
|
+
],
|
|
82
|
+
description: "global_search 检索库,默认 all。"
|
|
323
83
|
},
|
|
324
84
|
model: {
|
|
325
85
|
type: "string",
|
|
326
|
-
description: "zhida-thinking-1p5
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
output: {
|
|
330
|
-
schema: {
|
|
331
|
-
type: "object",
|
|
332
|
-
additionalProperties: false,
|
|
333
|
-
properties: {
|
|
334
|
-
version: {
|
|
335
|
-
type: "integer",
|
|
336
|
-
required: true
|
|
337
|
-
},
|
|
338
|
-
query: {
|
|
339
|
-
type: "string",
|
|
340
|
-
required: true
|
|
341
|
-
},
|
|
342
|
-
model: {
|
|
343
|
-
type: "string",
|
|
344
|
-
required: true
|
|
345
|
-
},
|
|
346
|
-
content: {
|
|
347
|
-
type: "string",
|
|
348
|
-
required: true
|
|
349
|
-
},
|
|
350
|
-
reasoning: {
|
|
351
|
-
type: "string",
|
|
352
|
-
required: true
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
},
|
|
356
|
-
render(_args, value) {
|
|
357
|
-
return [{
|
|
358
|
-
type: "text",
|
|
359
|
-
text: renderZhihuAsk(value)
|
|
360
|
-
}];
|
|
361
|
-
}
|
|
362
|
-
},
|
|
363
|
-
isConcurrencySafe() {
|
|
364
|
-
return true;
|
|
365
|
-
},
|
|
366
|
-
async execute(args, exec) {
|
|
367
|
-
const typed = args;
|
|
368
|
-
const model = ZHIHU_ASK_MODELS.includes(typed.model ?? "") ? typed.model : ZHIHU_ASK_DEFAULT_MODEL;
|
|
369
|
-
return await metered(onExecuted, () => executeZhihuAsk(typed.query, model, {
|
|
370
|
-
...client,
|
|
371
|
-
signal: exec.signal
|
|
372
|
-
}), (result) => result.content ? 1 : 0);
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
function createZhihuKnowledgeSearchTool(options = {}) {
|
|
377
|
-
const { onExecuted, ...client } = options;
|
|
378
|
-
return defineTool({
|
|
379
|
-
name: ZHIHU_KNOWLEDGE_SEARCH_TOOL_NAME,
|
|
380
|
-
description: "知乎知识库检索(POST /api/v1/knowledge/search,RAG 片段),默认只查公开库;网页端上传过资料后可加 personal/subscription 召回;仅作背景参考,不构成 canon,不写入项目文件。",
|
|
381
|
-
parameters: {
|
|
382
|
-
query: {
|
|
383
|
-
type: "string",
|
|
384
|
-
required: true,
|
|
385
|
-
description: "检索词。"
|
|
386
|
-
},
|
|
387
|
-
limit: {
|
|
388
|
-
type: "integer",
|
|
389
|
-
description: `返回条数,1-10,默认 5。`
|
|
86
|
+
description: "ask 模型:zhida-thinking-1p5(默认,带思考)、zhida-fast-1p5(简单事实)、zhida-agent(最慢最强,仅明确要求时用);免费额度不足被拒绝。"
|
|
390
87
|
},
|
|
391
88
|
recallScopes: {
|
|
392
89
|
type: "array",
|
|
393
|
-
description: "
|
|
90
|
+
description: "knowledge_search 召回范围,默认 public;可加 personal/subscription。",
|
|
394
91
|
items: {
|
|
395
92
|
type: "string",
|
|
396
93
|
enum: [...ZHIHU_RECALL_SCOPES]
|
|
@@ -400,54 +97,13 @@ function createZhihuKnowledgeSearchTool(options = {}) {
|
|
|
400
97
|
output: {
|
|
401
98
|
schema: {
|
|
402
99
|
type: "object",
|
|
403
|
-
additionalProperties:
|
|
404
|
-
properties: {
|
|
405
|
-
version: {
|
|
406
|
-
type: "integer",
|
|
407
|
-
required: true
|
|
408
|
-
},
|
|
409
|
-
query: {
|
|
410
|
-
type: "string",
|
|
411
|
-
required: true
|
|
412
|
-
},
|
|
413
|
-
limit: {
|
|
414
|
-
type: "integer",
|
|
415
|
-
required: true
|
|
416
|
-
},
|
|
417
|
-
recallScopes: {
|
|
418
|
-
type: "array",
|
|
419
|
-
required: true,
|
|
420
|
-
items: { type: "string" }
|
|
421
|
-
},
|
|
422
|
-
items: {
|
|
423
|
-
type: "array",
|
|
424
|
-
required: true,
|
|
425
|
-
items: {
|
|
426
|
-
type: "object",
|
|
427
|
-
additionalProperties: false,
|
|
428
|
-
properties: {
|
|
429
|
-
docName: {
|
|
430
|
-
type: "string",
|
|
431
|
-
required: true
|
|
432
|
-
},
|
|
433
|
-
originUrl: {
|
|
434
|
-
type: "string",
|
|
435
|
-
required: true
|
|
436
|
-
},
|
|
437
|
-
snippets: {
|
|
438
|
-
type: "array",
|
|
439
|
-
required: true,
|
|
440
|
-
items: { type: "string" }
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
100
|
+
additionalProperties: true,
|
|
101
|
+
properties: {}
|
|
446
102
|
},
|
|
447
|
-
render(
|
|
103
|
+
render(args, value) {
|
|
448
104
|
return [{
|
|
449
105
|
type: "text",
|
|
450
|
-
text:
|
|
106
|
+
text: renderResearch(args.action, value)
|
|
451
107
|
}];
|
|
452
108
|
}
|
|
453
109
|
},
|
|
@@ -456,10 +112,21 @@ function createZhihuKnowledgeSearchTool(options = {}) {
|
|
|
456
112
|
},
|
|
457
113
|
async execute(args, exec) {
|
|
458
114
|
const typed = args;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
115
|
+
if (typed.action !== "hot_list" && (typeof typed.query !== "string" || !typed.query.trim())) throw new ZhihuSearchError("INVALID_ARGUMENTS", `action ${typed.action} 需要 query 参数。`);
|
|
116
|
+
try {
|
|
117
|
+
const { result, results } = await executeResearch(typed.action, typed, client, exec.signal);
|
|
118
|
+
reportExecuted(onExecuted, {
|
|
119
|
+
ok: true,
|
|
120
|
+
results
|
|
121
|
+
});
|
|
122
|
+
return result;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
reportExecuted(onExecuted, {
|
|
125
|
+
ok: false,
|
|
126
|
+
results: 0
|
|
127
|
+
});
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
463
130
|
}
|
|
464
131
|
});
|
|
465
132
|
}
|
|
@@ -528,69 +195,59 @@ function renderZhihuOpenPlatform(result) {
|
|
|
528
195
|
}
|
|
529
196
|
//#endregion
|
|
530
197
|
//#region src/open-platform-tools.ts
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
const DATE_PARAMETERS = {
|
|
542
|
-
startDate: {
|
|
543
|
-
type: "string",
|
|
544
|
-
description: "YYYY-MM-DD,必须与 endDate 同时提供。省略两者使用上游默认范围,不猜测天数。"
|
|
545
|
-
},
|
|
546
|
-
endDate: {
|
|
547
|
-
type: "string",
|
|
548
|
-
description: "YYYY-MM-DD,不得早于 startDate。"
|
|
549
|
-
}
|
|
198
|
+
const ZHIHU_ACCOUNT_ACTIONS = {
|
|
199
|
+
question_recommendations: "question.recommendations",
|
|
200
|
+
question_answers: "question.answers",
|
|
201
|
+
content_detail: "content.detail",
|
|
202
|
+
content_comments: "content.comments",
|
|
203
|
+
creator_account_stats: "creator.account.stats",
|
|
204
|
+
creator_content_stats: "creator.content.stats",
|
|
205
|
+
quota: "quota"
|
|
550
206
|
};
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
207
|
+
const REQUIRED = {
|
|
208
|
+
question_recommendations: "主题 query 可选;省略按画像推荐。",
|
|
209
|
+
question_answers: "questionUrl 必填。",
|
|
210
|
+
content_detail: "contentUrl 必填。",
|
|
211
|
+
content_comments: "contentUrl 必填。",
|
|
212
|
+
creator_account_stats: "contentType 与日期可选。",
|
|
213
|
+
creator_content_stats: "contentUrl 必填。",
|
|
214
|
+
quota: "apiIds 可选。"
|
|
555
215
|
};
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
216
|
+
function createZhihuAccountTool(options = {}) {
|
|
217
|
+
const { onExecuted, ...client } = options;
|
|
218
|
+
return defineTool({
|
|
219
|
+
name: ZHIHU_ACCOUNT_TOOL_NAME,
|
|
220
|
+
description: "知乎账号数据(Access Secret 鉴权,拒绝 OAuth 切换;结果仅参考,不写入项目文件)。action:question_recommendations 问题推荐;question_answers 回答摘要;content_detail 创作全文;content_comments 评论;creator_account_stats 账号数据;creator_content_stats 单篇数据;quota 额度。",
|
|
560
221
|
parameters: {
|
|
222
|
+
action: {
|
|
223
|
+
type: "string",
|
|
224
|
+
enum: Object.keys(ZHIHU_ACCOUNT_ACTIONS),
|
|
225
|
+
required: true
|
|
226
|
+
},
|
|
561
227
|
query: {
|
|
562
228
|
type: "string",
|
|
563
|
-
description: "
|
|
229
|
+
description: "question_recommendations 主题;省略按画像推荐。"
|
|
564
230
|
},
|
|
565
231
|
count: {
|
|
566
232
|
type: "integer",
|
|
567
|
-
description: "
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
"question.answers": {
|
|
572
|
-
name: ZHIHU_QUESTION_ANSWERS_TOOL_NAME,
|
|
573
|
-
description: "读取问题下的回答摘要,非全文,也非新生成的 AI 摘要。一次一页,只有 paging.canContinue=true 时才用 nextOffset。使用 question_discovery 额度。",
|
|
574
|
-
parameters: {
|
|
233
|
+
description: "question_recommendations 数量,1-20,默认 5。"
|
|
234
|
+
},
|
|
575
235
|
questionUrl: {
|
|
576
236
|
type: "string",
|
|
577
|
-
|
|
578
|
-
|
|
237
|
+
description: "question_answers 必填,https://www.zhihu.com/question/{id} 链接。"
|
|
238
|
+
},
|
|
239
|
+
contentUrl: {
|
|
240
|
+
type: "string",
|
|
241
|
+
description: "content_detail、content_comments、creator_content_stats 必填:本人已发布的 HTTPS 回答/专栏/想法/视频链接。"
|
|
242
|
+
},
|
|
243
|
+
offset: {
|
|
244
|
+
type: "string",
|
|
245
|
+
description: "question_answers、content_comments 分页,非负 Int64 字符串,默认 \"0\";翻页只用 paging.nextOffset。"
|
|
246
|
+
},
|
|
247
|
+
limit: {
|
|
248
|
+
type: "integer",
|
|
249
|
+
description: "question_answers、content_comments 每页条数,1-50,默认 20。"
|
|
579
250
|
},
|
|
580
|
-
...PAGE_PARAMETERS
|
|
581
|
-
}
|
|
582
|
-
},
|
|
583
|
-
"content.detail": {
|
|
584
|
-
name: ZHIHU_USER_CONTENT_DETAIL_TOOL_NAME,
|
|
585
|
-
description: "读取当前账号已发布创作的全文。不能读其他账号全文;视频只给关联正文。空正文不能视为全文。使用 creator 额度。",
|
|
586
|
-
parameters: { contentUrl: CONTENT_URL }
|
|
587
|
-
},
|
|
588
|
-
"content.comments": {
|
|
589
|
-
name: ZHIHU_USER_CONTENT_COMMENTS_TOOL_NAME,
|
|
590
|
-
description: "读取当前账号创作下的根评论及附带 Children;子评论不保证完整。一次一页,只按 paging 翻页,不按条数判断结束。使用 creator 额度。",
|
|
591
|
-
parameters: {
|
|
592
|
-
contentUrl: CONTENT_URL,
|
|
593
|
-
...PAGE_PARAMETERS,
|
|
594
251
|
order: {
|
|
595
252
|
type: "string",
|
|
596
253
|
enum: [
|
|
@@ -598,14 +255,8 @@ const DEFINITIONS = {
|
|
|
598
255
|
"reverse",
|
|
599
256
|
"ascending"
|
|
600
257
|
],
|
|
601
|
-
description: "排序,默认 score。"
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
},
|
|
605
|
-
"creator.account.stats": {
|
|
606
|
-
name: ZHIHU_CREATOR_ACCOUNT_STATS_TOOL_NAME,
|
|
607
|
-
description: "读取当前账号创作数据。缺失指标不补零,比例保持原值,不换算百分比。使用 creator 额度。",
|
|
608
|
-
parameters: {
|
|
258
|
+
description: "content_comments 排序,默认 score。"
|
|
259
|
+
},
|
|
609
260
|
contentType: {
|
|
610
261
|
type: "string",
|
|
611
262
|
enum: [
|
|
@@ -615,76 +266,31 @@ const DEFINITIONS = {
|
|
|
615
266
|
"pin",
|
|
616
267
|
"zvideo"
|
|
617
268
|
],
|
|
618
|
-
description: "内容类型,默认 all,不支持 question。"
|
|
269
|
+
description: "creator_account_stats 内容类型,默认 all,不支持 question。"
|
|
619
270
|
},
|
|
620
|
-
|
|
621
|
-
}
|
|
622
|
-
},
|
|
623
|
-
"creator.content.stats": {
|
|
624
|
-
name: ZHIHU_CREATOR_CONTENT_STATS_TOOL_NAME,
|
|
625
|
-
description: "读取当前账号单篇创作数据。空列表不代表零指标;缺失指标保持省略,比例保持上游原值。使用 creator 额度。",
|
|
626
|
-
parameters: {
|
|
627
|
-
contentUrl: CONTENT_URL,
|
|
628
|
-
...DATE_PARAMETERS
|
|
629
|
-
}
|
|
630
|
-
},
|
|
631
|
-
quota: {
|
|
632
|
-
name: ZHIHU_QUOTA_TOOL_NAME,
|
|
633
|
-
description: "查询官方每日额度,本接口不消耗业务额度。不同于本地 usage.summary;不推算余额或重置时间。",
|
|
634
|
-
parameters: { apiIds: {
|
|
635
|
-
type: "array",
|
|
636
|
-
items: {
|
|
271
|
+
startDate: {
|
|
637
272
|
type: "string",
|
|
638
|
-
|
|
273
|
+
description: "stats action 可选,YYYY-MM-DD,与 endDate 成对;都省略用上游默认范围。"
|
|
639
274
|
},
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
type: "integer",
|
|
650
|
-
required: true
|
|
651
|
-
},
|
|
652
|
-
operation: {
|
|
653
|
-
type: "string",
|
|
654
|
-
required: true
|
|
655
|
-
},
|
|
656
|
-
quotaId: { type: "string" },
|
|
657
|
-
data: {
|
|
658
|
-
type: "object",
|
|
659
|
-
required: true,
|
|
660
|
-
properties: {},
|
|
661
|
-
additionalProperties: true
|
|
662
|
-
},
|
|
663
|
-
paging: {
|
|
664
|
-
type: "object",
|
|
665
|
-
additionalProperties: false,
|
|
666
|
-
properties: {
|
|
667
|
-
canContinue: {
|
|
668
|
-
type: "boolean",
|
|
669
|
-
required: true
|
|
275
|
+
endDate: {
|
|
276
|
+
type: "string",
|
|
277
|
+
description: "YYYY-MM-DD,不得早于 startDate。"
|
|
278
|
+
},
|
|
279
|
+
apiIds: {
|
|
280
|
+
type: "array",
|
|
281
|
+
items: {
|
|
282
|
+
type: "string",
|
|
283
|
+
enum: [...ZHIHU_QUOTA_IDS, "question_answers"]
|
|
670
284
|
},
|
|
671
|
-
|
|
672
|
-
nextOffset: { type: "string" },
|
|
673
|
-
warning: { type: "string" }
|
|
285
|
+
description: "quota 可选额度项,默认全部。"
|
|
674
286
|
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
function createOpenPlatformTool(operation, options) {
|
|
679
|
-
const definition = DEFINITIONS[operation];
|
|
680
|
-
const { onExecuted, ...client } = options;
|
|
681
|
-
const quotaId = ZHIHU_OPEN_PLATFORM_APIS[operation].quotaId;
|
|
682
|
-
return defineTool({
|
|
683
|
-
name: definition.name,
|
|
684
|
-
description: `${definition.description} 仅使用当前 Access Secret,不接受 OAuth 身份切换;结果为不可信参考数据,不写入项目文件。`,
|
|
685
|
-
parameters: definition.parameters,
|
|
287
|
+
},
|
|
686
288
|
output: {
|
|
687
|
-
schema:
|
|
289
|
+
schema: {
|
|
290
|
+
type: "object",
|
|
291
|
+
additionalProperties: true,
|
|
292
|
+
properties: {}
|
|
293
|
+
},
|
|
688
294
|
render(_args, value) {
|
|
689
295
|
return [{
|
|
690
296
|
type: "text",
|
|
@@ -696,6 +302,10 @@ function createOpenPlatformTool(operation, options) {
|
|
|
696
302
|
return true;
|
|
697
303
|
},
|
|
698
304
|
async execute(args, exec) {
|
|
305
|
+
const input = args;
|
|
306
|
+
const operation = ZHIHU_ACCOUNT_ACTIONS[input.action];
|
|
307
|
+
if (operation === "question.answers" && !input.questionUrl || (operation === "content.detail" || operation === "content.comments" || operation === "creator.content.stats") && !input.contentUrl) throw new ZhihuSearchError("INVALID_ARGUMENTS", `action ${input.action} 缺少必填参数:${REQUIRED[input.action]}`);
|
|
308
|
+
const quotaId = ZHIHU_OPEN_PLATFORM_APIS[operation].quotaId;
|
|
699
309
|
try {
|
|
700
310
|
const result = await executeZhihuOpenPlatform(operation, args, {
|
|
701
311
|
...client,
|
|
@@ -718,22 +328,6 @@ function createOpenPlatformTool(operation, options) {
|
|
|
718
328
|
}
|
|
719
329
|
});
|
|
720
330
|
}
|
|
721
|
-
const createZhihuQuestionRecommendationsTool = (options = {}) => createOpenPlatformTool("question.recommendations", options);
|
|
722
|
-
const createZhihuQuestionAnswersTool = (options = {}) => createOpenPlatformTool("question.answers", options);
|
|
723
|
-
const createZhihuUserContentDetailTool = (options = {}) => createOpenPlatformTool("content.detail", options);
|
|
724
|
-
const createZhihuUserContentCommentsTool = (options = {}) => createOpenPlatformTool("content.comments", options);
|
|
725
|
-
const createZhihuCreatorAccountStatsTool = (options = {}) => createOpenPlatformTool("creator.account.stats", options);
|
|
726
|
-
const createZhihuCreatorContentStatsTool = (options = {}) => createOpenPlatformTool("creator.content.stats", options);
|
|
727
|
-
const createZhihuQuotaTool = (options = {}) => createOpenPlatformTool("quota", options);
|
|
728
|
-
const ZHIHU_OPEN_PLATFORM_TOOL_FACTORIES = [
|
|
729
|
-
createZhihuQuestionRecommendationsTool,
|
|
730
|
-
createZhihuQuestionAnswersTool,
|
|
731
|
-
createZhihuUserContentDetailTool,
|
|
732
|
-
createZhihuUserContentCommentsTool,
|
|
733
|
-
createZhihuCreatorAccountStatsTool,
|
|
734
|
-
createZhihuCreatorContentStatsTool,
|
|
735
|
-
createZhihuQuotaTool
|
|
736
|
-
];
|
|
737
331
|
//#endregion
|
|
738
332
|
//#region src/sync-tools.ts
|
|
739
333
|
/** Publishing is a human confirmation action in the preview pane. The tool can
|
|
@@ -741,7 +335,7 @@ const ZHIHU_OPEN_PLATFORM_TOOL_FACTORIES = [
|
|
|
741
335
|
function createZhihuSyncTool(service) {
|
|
742
336
|
return defineTool({
|
|
743
337
|
name: "zhihu_sync",
|
|
744
|
-
description: "
|
|
338
|
+
description: "管理知乎文章、提问、想法草稿,校验预览、上传配图(发送到知乎)。发布需在预览界面确认,当前分支未提供发布界面。",
|
|
745
339
|
parameters: {
|
|
746
340
|
action: {
|
|
747
341
|
type: "string",
|
|
@@ -756,7 +350,7 @@ function createZhihuSyncTool(service) {
|
|
|
756
350
|
},
|
|
757
351
|
offset: {
|
|
758
352
|
type: "integer",
|
|
759
|
-
description: "list
|
|
353
|
+
description: "list 分页位置;后续用返回的 nextOffset。"
|
|
760
354
|
},
|
|
761
355
|
id: {
|
|
762
356
|
type: "string",
|
|
@@ -764,11 +358,11 @@ function createZhihuSyncTool(service) {
|
|
|
764
358
|
},
|
|
765
359
|
expectedRevision: {
|
|
766
360
|
type: "integer",
|
|
767
|
-
description: "prepare
|
|
361
|
+
description: "prepare 或更新时填写上次读到的 revision。"
|
|
768
362
|
},
|
|
769
363
|
image: {
|
|
770
364
|
type: "object",
|
|
771
|
-
description: "upload_image
|
|
365
|
+
description: "upload_image 的图片。",
|
|
772
366
|
properties: {
|
|
773
367
|
fileName: {
|
|
774
368
|
type: "string",
|
|
@@ -777,7 +371,7 @@ function createZhihuSyncTool(service) {
|
|
|
777
371
|
contentBase64: {
|
|
778
372
|
type: "string",
|
|
779
373
|
required: true,
|
|
780
|
-
description: "JPEG
|
|
374
|
+
description: "JPEG/PNG/GIF/WebP/BMP;GIF ≤15 MB,其他 ≤30 MB。"
|
|
781
375
|
},
|
|
782
376
|
scene: {
|
|
783
377
|
type: "string",
|
|
@@ -793,7 +387,7 @@ function createZhihuSyncTool(service) {
|
|
|
793
387
|
},
|
|
794
388
|
draft: {
|
|
795
389
|
type: "object",
|
|
796
|
-
description: "save
|
|
390
|
+
description: "save 的草稿;只适配格式,不改正文。",
|
|
797
391
|
properties: {
|
|
798
392
|
type: {
|
|
799
393
|
type: "string",
|
|
@@ -819,7 +413,7 @@ function createZhihuSyncTool(service) {
|
|
|
819
413
|
},
|
|
820
414
|
images: {
|
|
821
415
|
type: "array",
|
|
822
|
-
description: "
|
|
416
|
+
description: "upload_image 已上传的图片。",
|
|
823
417
|
items: {
|
|
824
418
|
type: "object",
|
|
825
419
|
properties: {
|
|
@@ -841,7 +435,7 @@ function createZhihuSyncTool(service) {
|
|
|
841
435
|
},
|
|
842
436
|
linkCard: {
|
|
843
437
|
type: "object",
|
|
844
|
-
description: "
|
|
438
|
+
description: "想法的链接卡片(与图片互斥)。",
|
|
845
439
|
properties: {
|
|
846
440
|
url: {
|
|
847
441
|
type: "string",
|
|
@@ -880,11 +474,11 @@ function createZhihuSyncTool(service) {
|
|
|
880
474
|
topics: {
|
|
881
475
|
type: "array",
|
|
882
476
|
items: { type: "string" },
|
|
883
|
-
description: "
|
|
477
|
+
description: "话题链接,文章最多 3 个、提问最多 5 个。"
|
|
884
478
|
},
|
|
885
479
|
ring: {
|
|
886
480
|
type: "string",
|
|
887
|
-
description: "
|
|
481
|
+
description: "想法的圈子链接。"
|
|
888
482
|
}
|
|
889
483
|
},
|
|
890
484
|
additionalProperties: false
|
|
@@ -929,14 +523,7 @@ function apply(ctx) {
|
|
|
929
523
|
const host = ctx;
|
|
930
524
|
const options = host.zhihu.toolOptions;
|
|
931
525
|
if (host.zhihu.syncCall) host.tools.register(createZhihuSyncTool(host.zhihu));
|
|
932
|
-
for (const create of [
|
|
933
|
-
createZhihuSearchTool,
|
|
934
|
-
createZhihuGlobalSearchTool,
|
|
935
|
-
createZhihuHotListTool,
|
|
936
|
-
createZhihuAskTool,
|
|
937
|
-
createZhihuKnowledgeSearchTool,
|
|
938
|
-
...ZHIHU_OPEN_PLATFORM_TOOL_FACTORIES
|
|
939
|
-
]) {
|
|
526
|
+
for (const create of [createZhihuResearchTool, createZhihuAccountTool]) {
|
|
940
527
|
const tool = create(options);
|
|
941
528
|
const execute = tool.execute;
|
|
942
529
|
host.tools.register({
|