Initial commit: import Operit protocol plugins from xiaoli-cli
This commit is contained in:
commit
c6600fc47d
52 files changed
+31492
No files matched your search
@@ -0,0 +1,237 @@
|
||||
/* METADATA
|
||||
{
|
||||
"name": "zhipu_search",
|
||||
"display_name": {
|
||||
"zh": "智谱搜索",
|
||||
"en": "Zhipu Search"
|
||||
},
|
||||
"description": {
|
||||
"zh": "智谱 AI 独立网络搜索 API,返回结构化搜索结果。",
|
||||
"en": "Zhipu AI standalone web search API with structured results."
|
||||
},
|
||||
"author": "浮生一梦",
|
||||
"env": [
|
||||
{
|
||||
"name": "ZHIPU_SEARCH_API_KEY",
|
||||
"description": {
|
||||
"zh": "智谱搜索专用 API Key(与生图 Key 独立)",
|
||||
"en": "Zhipu Search API Key (independent from draw Key)"
|
||||
},
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"category": "Search",
|
||||
"tools": [
|
||||
{
|
||||
"name": "search",
|
||||
"description": {
|
||||
"zh": "使用智谱 Web Search API 进行搜索",
|
||||
"en": "Search using Zhipu Web Search API"
|
||||
},
|
||||
"parameters": [
|
||||
{ "name": "query", "description": { "zh": "搜索关键词", "en": "Search query" }, "type": "string", "required": true },
|
||||
{ "name": "api_key", "description": { "zh": "智谱 API Key(可选,不传则读取环境变量)", "en": "Zhipu API Key" }, "type": "string", "required": false },
|
||||
{ "name": "engine", "description": { "zh": "搜索引擎:search_std/search_pro/search_pro_sogou/search_pro_quark", "en": "Search engine" }, "type": "string", "required": false },
|
||||
{ "name": "count", "description": { "zh": "返回结果数 (1-50),默认 10", "en": "Result count (1-50)" }, "type": "number", "required": false },
|
||||
{ "name": "recency", "description": { "zh": "时间范围:oneDay/oneWeek/oneMonth/oneYear/noLimit", "en": "Time range" }, "type": "string", "required": false },
|
||||
{ "name": "content_size", "description": { "zh": "内容长度:medium/high", "en": "Content size" }, "type": "string", "required": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"description": {
|
||||
"zh": "测试 API 连接",
|
||||
"en": "Test API connection"
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
}*/
|
||||
|
||||
/// <reference path="./types/index.d.ts" />
|
||||
|
||||
const zhipuSearch = (function () {
|
||||
const API_URL = "https://open.bigmodel.cn/api/paas/v4/web_search";
|
||||
const TIMEOUT = 60000;
|
||||
const client = OkHttp.newBuilder()
|
||||
.connectTimeout(TIMEOUT)
|
||||
.readTimeout(TIMEOUT)
|
||||
.writeTimeout(TIMEOUT)
|
||||
.build();
|
||||
|
||||
type SearchParams = {
|
||||
query: string;
|
||||
api_key?: string;
|
||||
engine?: string;
|
||||
count?: number;
|
||||
recency?: string;
|
||||
content_size?: string;
|
||||
};
|
||||
|
||||
type ZhipuSearchItem = {
|
||||
title?: string;
|
||||
content?: string;
|
||||
link?: string;
|
||||
media?: string;
|
||||
icon?: string;
|
||||
publish_date?: string;
|
||||
refer?: string;
|
||||
};
|
||||
|
||||
type ZhipuSearchResponse = {
|
||||
id?: string;
|
||||
search_result?: ZhipuSearchItem[];
|
||||
search_intent?: string[];
|
||||
};
|
||||
|
||||
type SearchResult = {
|
||||
success: true;
|
||||
query: string;
|
||||
id?: string;
|
||||
intent: string | null;
|
||||
results: ZhipuSearchItem[];
|
||||
count: number;
|
||||
};
|
||||
|
||||
type TestResult = {
|
||||
success: true;
|
||||
latency: number;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
function getApiKey(providedKey?: string): string {
|
||||
if (providedKey) return providedKey;
|
||||
let key = getEnv("ZHIPU_SEARCH_API_KEY");
|
||||
if (key) return key;
|
||||
key = getEnv("DEFAULT_API_KEY");
|
||||
return key || "";
|
||||
}
|
||||
|
||||
async function httpPost(body: Record<string, any>, apiKey?: string | null): Promise<ZhipuSearchResponse> {
|
||||
const key = getApiKey(apiKey || undefined);
|
||||
if (!key) {
|
||||
throw new Error("未设置 API Key,请配置 ZHIPU_SEARCH_API_KEY 环境变量或在调用时传入 api_key 参数");
|
||||
}
|
||||
|
||||
const request = client
|
||||
.newRequest()
|
||||
.url(API_URL)
|
||||
.method("POST")
|
||||
.header("Authorization", "Bearer " + key)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(JSON.stringify(body), "json");
|
||||
|
||||
const response = await request.build().execute();
|
||||
const content = response.content;
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
throw new Error("HTTP " + response.statusCode + ": " + content);
|
||||
}
|
||||
|
||||
return JSON.parse(content) as ZhipuSearchResponse;
|
||||
}
|
||||
|
||||
async function search(params: SearchParams): Promise<SearchResult> {
|
||||
const body: Record<string, any> = {
|
||||
search_query: params.query,
|
||||
search_engine: params.engine || "search_std",
|
||||
search_intent: true,
|
||||
count: params.count || 10,
|
||||
content_size: params.content_size || "medium"
|
||||
};
|
||||
|
||||
if (params.recency) {
|
||||
body.search_recency_filter = params.recency;
|
||||
}
|
||||
|
||||
const result = await httpPost(body, params.api_key);
|
||||
|
||||
let results: ZhipuSearchItem[] = [];
|
||||
if (result.search_result && Array.isArray(result.search_result)) {
|
||||
results = result.search_result.map((item) => ({
|
||||
title: item.title,
|
||||
content: item.content,
|
||||
link: item.link,
|
||||
media: item.media,
|
||||
icon: item.icon,
|
||||
publish_date: item.publish_date,
|
||||
refer: item.refer
|
||||
}));
|
||||
}
|
||||
|
||||
let intent: string | null = null;
|
||||
if (result.search_intent && result.search_intent.length > 0) {
|
||||
intent = result.search_intent[0] || null;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
query: params.query,
|
||||
id: result.id,
|
||||
intent,
|
||||
results,
|
||||
count: results.length
|
||||
};
|
||||
}
|
||||
|
||||
async function test(): Promise<TestResult> {
|
||||
const body = {
|
||||
search_query: "hi",
|
||||
search_engine: "search_std",
|
||||
search_intent: false,
|
||||
count: 1
|
||||
};
|
||||
|
||||
const start = Date.now();
|
||||
const result = await httpPost(body, null);
|
||||
const latency = Date.now() - start;
|
||||
|
||||
return {
|
||||
success: true,
|
||||
latency,
|
||||
id: result.id
|
||||
};
|
||||
}
|
||||
|
||||
async function searchWrapper(params: SearchParams) {
|
||||
try {
|
||||
const result = await search(params);
|
||||
complete({
|
||||
success: true,
|
||||
message: "搜索完成,找到 " + result.count + " 条结果",
|
||||
data: result
|
||||
});
|
||||
} catch (error: any) {
|
||||
complete({
|
||||
success: false,
|
||||
message: "搜索失败:" + error.message,
|
||||
error_stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function testWrapper() {
|
||||
try {
|
||||
const result = await test();
|
||||
complete({
|
||||
success: true,
|
||||
message: "连接成功,延迟 " + result.latency + "ms",
|
||||
data: result
|
||||
});
|
||||
} catch (error: any) {
|
||||
complete({
|
||||
success: false,
|
||||
message: "测试失败:" + error.message,
|
||||
error_stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
search: searchWrapper,
|
||||
test: testWrapper
|
||||
};
|
||||
})();
|
||||
|
||||
exports.search = zhipuSearch.search;
|
||||
exports.test = zhipuSearch.test;
|
||||
Reference in new issue
Block a user