openhorse 0.1.18 → 0.1.19
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 -1
- package/dist/framework/tool.d.ts +1 -0
- package/dist/framework/tool.d.ts.map +1 -1
- package/dist/framework/tool.js.map +1 -1
- package/dist/services/config.d.ts +4 -2
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +42 -0
- package/dist/services/config.js.map +1 -1
- package/dist/services/global-config.d.ts +23 -0
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/web-search-adapters.d.ts +24 -0
- package/dist/services/web-search-adapters.d.ts.map +1 -0
- package/dist/services/web-search-adapters.js +338 -0
- package/dist/services/web-search-adapters.js.map +1 -0
- package/dist/services/web-search-mcp.d.ts +32 -0
- package/dist/services/web-search-mcp.d.ts.map +1 -0
- package/dist/services/web-search-mcp.js +251 -0
- package/dist/services/web-search-mcp.js.map +1 -0
- package/dist/services/web-search-provider.d.ts +33 -0
- package/dist/services/web-search-provider.d.ts.map +1 -0
- package/dist/services/web-search-provider.js +139 -0
- package/dist/services/web-search-provider.js.map +1 -0
- package/dist/tools/web.d.ts +2 -2
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +95 -139
- package/dist/tools/web.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote WebSearch MCP client.
|
|
3
|
+
*
|
|
4
|
+
* The built-in web_search tool delegates search to a provider MCP service
|
|
5
|
+
* instead of scraping search-engine HTML locally.
|
|
6
|
+
*/
|
|
7
|
+
import type { WebSearchMcpConfig } from './config';
|
|
8
|
+
export declare const DEFAULT_WEBSEARCH_MCP_ENDPOINT = "https://dashscope.aliyuncs.com/api/v1/mcps/WebSearch/mcp";
|
|
9
|
+
export interface WebSearchMcpSearchResult {
|
|
10
|
+
output: string;
|
|
11
|
+
toolName: string;
|
|
12
|
+
endpoint: string;
|
|
13
|
+
provider?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class WebSearchMcpError extends Error {
|
|
16
|
+
readonly type: string;
|
|
17
|
+
readonly endpoint: string;
|
|
18
|
+
constructor(type: string, message: string, endpoint: string);
|
|
19
|
+
}
|
|
20
|
+
export declare class WebSearchMcpClient {
|
|
21
|
+
private readonly config;
|
|
22
|
+
private initialized;
|
|
23
|
+
private sessionId;
|
|
24
|
+
private tools;
|
|
25
|
+
constructor(config?: WebSearchMcpConfig);
|
|
26
|
+
search(query: string, limit?: number): Promise<WebSearchMcpSearchResult>;
|
|
27
|
+
private ensureInitialized;
|
|
28
|
+
private notification;
|
|
29
|
+
private request;
|
|
30
|
+
private sendJsonRpc;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=web-search-mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search-mcp.d.ts","sourceRoot":"","sources":["../../src/services/web-search-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGnD,eAAO,MAAM,8BAA8B,6DAAiC,CAAC;AAkC7E,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAM5D;AAwHD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,KAAK,CAA2B;gBAE5B,MAAM,CAAC,EAAE,kBAAkB;IAIjC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;YAqBhE,iBAAiB;YA6BjB,YAAY;YAIZ,OAAO;YAoBP,WAAW;CA+E1B"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Remote WebSearch MCP client.
|
|
4
|
+
*
|
|
5
|
+
* The built-in web_search tool delegates search to a provider MCP service
|
|
6
|
+
* instead of scraping search-engine HTML locally.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.WebSearchMcpClient = exports.WebSearchMcpError = exports.DEFAULT_WEBSEARCH_MCP_ENDPOINT = void 0;
|
|
10
|
+
const web_search_provider_1 = require("./web-search-provider");
|
|
11
|
+
exports.DEFAULT_WEBSEARCH_MCP_ENDPOINT = web_search_provider_1.BAILIAN_WEBSEARCH_MCP_ENDPOINT;
|
|
12
|
+
const MCP_PROTOCOL_VERSION = '2025-03-26';
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 30000;
|
|
14
|
+
class WebSearchMcpError extends Error {
|
|
15
|
+
constructor(type, message, endpoint) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'WebSearchMcpError';
|
|
18
|
+
this.type = type;
|
|
19
|
+
this.endpoint = endpoint;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.WebSearchMcpError = WebSearchMcpError;
|
|
23
|
+
function resolveConfig(config = {}) {
|
|
24
|
+
return {
|
|
25
|
+
endpoint: config.endpoint || exports.DEFAULT_WEBSEARCH_MCP_ENDPOINT,
|
|
26
|
+
provider: config.provider,
|
|
27
|
+
apiKey: config.apiKey,
|
|
28
|
+
toolName: config.toolName,
|
|
29
|
+
timeoutMs: config.timeoutMs || DEFAULT_TIMEOUT_MS,
|
|
30
|
+
authType: config.authType,
|
|
31
|
+
apiKeyHeader: config.apiKeyHeader,
|
|
32
|
+
apiKeyQueryParam: config.apiKeyQueryParam,
|
|
33
|
+
headers: config.headers || {},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function parseSseMessages(text) {
|
|
37
|
+
const messages = [];
|
|
38
|
+
const events = text.split(/\n\n+/);
|
|
39
|
+
for (const event of events) {
|
|
40
|
+
const dataLines = event
|
|
41
|
+
.split(/\r?\n/)
|
|
42
|
+
.filter(line => line.startsWith('data:'))
|
|
43
|
+
.map(line => line.slice('data:'.length).trim());
|
|
44
|
+
if (dataLines.length === 0)
|
|
45
|
+
continue;
|
|
46
|
+
const data = dataLines.join('\n');
|
|
47
|
+
if (!data || data === '[DONE]')
|
|
48
|
+
continue;
|
|
49
|
+
try {
|
|
50
|
+
messages.push(JSON.parse(data));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Ignore non-JSON SSE frames.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return messages;
|
|
57
|
+
}
|
|
58
|
+
function parseJsonRpcMessages(text, contentType) {
|
|
59
|
+
if (!text.trim())
|
|
60
|
+
return [];
|
|
61
|
+
if (contentType.includes('text/event-stream')) {
|
|
62
|
+
return parseSseMessages(text);
|
|
63
|
+
}
|
|
64
|
+
const parsed = JSON.parse(text);
|
|
65
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
66
|
+
}
|
|
67
|
+
function withTimeout(timeoutMs) {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
70
|
+
timer.unref?.();
|
|
71
|
+
return {
|
|
72
|
+
signal: controller.signal,
|
|
73
|
+
cleanup: () => clearTimeout(timer),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function normalizeMcpOutput(result) {
|
|
77
|
+
if (Array.isArray(result?.content)) {
|
|
78
|
+
const text = result.content
|
|
79
|
+
.filter((item) => item?.type === 'text' && typeof item.text === 'string')
|
|
80
|
+
.map((item) => item.text)
|
|
81
|
+
.join('\n');
|
|
82
|
+
if (text)
|
|
83
|
+
return text;
|
|
84
|
+
}
|
|
85
|
+
if (result?.structuredContent) {
|
|
86
|
+
return JSON.stringify(result.structuredContent, null, 2);
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify(result, null, 2);
|
|
89
|
+
}
|
|
90
|
+
function selectSearchTool(tools, preferred) {
|
|
91
|
+
if (tools.length === 0) {
|
|
92
|
+
throw new Error('WebSearch MCP returned no tools');
|
|
93
|
+
}
|
|
94
|
+
const candidates = [
|
|
95
|
+
preferred,
|
|
96
|
+
'web_search',
|
|
97
|
+
'webSearch',
|
|
98
|
+
'WebSearch',
|
|
99
|
+
'search',
|
|
100
|
+
'Search',
|
|
101
|
+
'webSearchPrime',
|
|
102
|
+
].filter(Boolean);
|
|
103
|
+
for (const name of candidates) {
|
|
104
|
+
const exact = tools.find(tool => tool.name === name);
|
|
105
|
+
if (exact)
|
|
106
|
+
return exact;
|
|
107
|
+
}
|
|
108
|
+
const fuzzy = tools.find(tool => /search/i.test(tool.name));
|
|
109
|
+
return fuzzy || tools[0];
|
|
110
|
+
}
|
|
111
|
+
function buildSearchArgs(tool, query, limit) {
|
|
112
|
+
const properties = tool.inputSchema?.properties || {};
|
|
113
|
+
const args = {};
|
|
114
|
+
const queryKey = ['query', 'q', 'keyword', 'keywords', 'search_query', 'searchQuery', 'input']
|
|
115
|
+
.find(key => Object.prototype.hasOwnProperty.call(properties, key));
|
|
116
|
+
args[queryKey || 'query'] = query;
|
|
117
|
+
if (limit && limit > 0) {
|
|
118
|
+
const limitKey = ['limit', 'count', 'num_results', 'max_results', 'top_k', 'topK', 'page_size', 'pageSize']
|
|
119
|
+
.find(key => Object.prototype.hasOwnProperty.call(properties, key));
|
|
120
|
+
if (limitKey) {
|
|
121
|
+
args[limitKey] = limit;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return args;
|
|
125
|
+
}
|
|
126
|
+
class WebSearchMcpClient {
|
|
127
|
+
constructor(config) {
|
|
128
|
+
this.initialized = false;
|
|
129
|
+
this.sessionId = null;
|
|
130
|
+
this.tools = [];
|
|
131
|
+
this.config = resolveConfig(config);
|
|
132
|
+
}
|
|
133
|
+
async search(query, limit) {
|
|
134
|
+
await this.ensureInitialized();
|
|
135
|
+
const tool = selectSearchTool(this.tools, this.config.toolName);
|
|
136
|
+
const result = await this.request('tools/call', {
|
|
137
|
+
name: tool.name,
|
|
138
|
+
arguments: buildSearchArgs(tool, query, limit),
|
|
139
|
+
});
|
|
140
|
+
if (result?.isError) {
|
|
141
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_TOOL_ERROR', normalizeMcpOutput(result), this.config.endpoint);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
output: normalizeMcpOutput(result),
|
|
145
|
+
toolName: tool.name,
|
|
146
|
+
endpoint: this.config.endpoint,
|
|
147
|
+
provider: this.config.provider,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
async ensureInitialized() {
|
|
151
|
+
if (this.initialized)
|
|
152
|
+
return;
|
|
153
|
+
if (this.config.authType !== 'none'
|
|
154
|
+
&& !this.config.apiKey
|
|
155
|
+
&& !this.config.headers.Authorization
|
|
156
|
+
&& !this.config.headers.authorization) {
|
|
157
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_NOT_CONFIGURED', 'WebSearch MCP API key is not configured. Set webSearch.apiKey, OPENHORSE_WEBSEARCH_API_KEY, a provider API key env var, or the OpenHorse apiKey.', this.config.endpoint);
|
|
158
|
+
}
|
|
159
|
+
await this.request('initialize', {
|
|
160
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
161
|
+
capabilities: {},
|
|
162
|
+
clientInfo: { name: 'openhorse', version: '0.1.18' },
|
|
163
|
+
});
|
|
164
|
+
await this.notification('notifications/initialized', {});
|
|
165
|
+
const toolsResult = await this.request('tools/list', {});
|
|
166
|
+
this.tools = toolsResult?.tools || [];
|
|
167
|
+
this.initialized = true;
|
|
168
|
+
}
|
|
169
|
+
async notification(method, params) {
|
|
170
|
+
await this.sendJsonRpc({ jsonrpc: '2.0', method, params });
|
|
171
|
+
}
|
|
172
|
+
async request(method, params) {
|
|
173
|
+
const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
174
|
+
const message = { jsonrpc: '2.0', id, method, params };
|
|
175
|
+
const messages = await this.sendJsonRpc(message);
|
|
176
|
+
const response = messages.find(msg => String(msg.id) === id) || messages[0];
|
|
177
|
+
if (!response) {
|
|
178
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_EMPTY_RESPONSE', `Empty MCP response for ${method}`, this.config.endpoint);
|
|
179
|
+
}
|
|
180
|
+
if (response.error) {
|
|
181
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_RPC_ERROR', response.error.message || `MCP ${method} failed`, this.config.endpoint);
|
|
182
|
+
}
|
|
183
|
+
return response.result;
|
|
184
|
+
}
|
|
185
|
+
async sendJsonRpc(message) {
|
|
186
|
+
const authType = this.config.authType || 'bearer';
|
|
187
|
+
const headers = {
|
|
188
|
+
'Content-Type': 'application/json',
|
|
189
|
+
'Accept': 'application/json, text/event-stream',
|
|
190
|
+
'MCP-Protocol-Version': MCP_PROTOCOL_VERSION,
|
|
191
|
+
...this.config.headers,
|
|
192
|
+
};
|
|
193
|
+
let endpoint = this.config.endpoint;
|
|
194
|
+
if (this.config.apiKey && authType === 'query') {
|
|
195
|
+
const url = new URL(endpoint);
|
|
196
|
+
url.searchParams.set(this.config.apiKeyQueryParam || 'api_key', this.config.apiKey);
|
|
197
|
+
endpoint = url.toString();
|
|
198
|
+
}
|
|
199
|
+
if (this.config.apiKey
|
|
200
|
+
&& authType !== 'none'
|
|
201
|
+
&& authType !== 'query'
|
|
202
|
+
&& !headers.Authorization
|
|
203
|
+
&& !headers.authorization) {
|
|
204
|
+
const headerName = this.config.apiKeyHeader || 'Authorization';
|
|
205
|
+
headers[headerName] = authType === 'header'
|
|
206
|
+
? this.config.apiKey
|
|
207
|
+
: `Bearer ${this.config.apiKey}`;
|
|
208
|
+
}
|
|
209
|
+
if (this.sessionId) {
|
|
210
|
+
headers['Mcp-Session-Id'] = this.sessionId;
|
|
211
|
+
}
|
|
212
|
+
const timeout = withTimeout(this.config.timeoutMs);
|
|
213
|
+
let response;
|
|
214
|
+
try {
|
|
215
|
+
response = await fetch(endpoint, {
|
|
216
|
+
method: 'POST',
|
|
217
|
+
headers,
|
|
218
|
+
body: JSON.stringify(message),
|
|
219
|
+
signal: timeout.signal,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
const message = err?.name === 'AbortError'
|
|
224
|
+
? `request timed out after ${this.config.timeoutMs}ms`
|
|
225
|
+
: err?.message || String(err);
|
|
226
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_NETWORK_ERROR', message, this.config.endpoint);
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
timeout.cleanup();
|
|
230
|
+
}
|
|
231
|
+
const sessionId = response.headers.get('mcp-session-id') || response.headers.get('Mcp-Session-Id');
|
|
232
|
+
if (sessionId) {
|
|
233
|
+
this.sessionId = sessionId;
|
|
234
|
+
}
|
|
235
|
+
if (response.status === 202 || response.status === 204) {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
const text = await response.text();
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_HTTP_ERROR', `HTTP ${response.status}: ${text || response.statusText}`, this.config.endpoint);
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return parseJsonRpcMessages(text, response.headers.get('content-type') || '');
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
throw new WebSearchMcpError('WEBSEARCH_MCP_PARSE_ERROR', `Failed to parse MCP response: ${err.message}`, this.config.endpoint);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
exports.WebSearchMcpClient = WebSearchMcpClient;
|
|
251
|
+
//# sourceMappingURL=web-search-mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search-mcp.js","sourceRoot":"","sources":["../../src/services/web-search-mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { OpenHorseCLIConfig, WebSearchMcpConfig } from './config';
|
|
2
|
+
export declare const BAILIAN_WEBSEARCH_MCP_ENDPOINT = "https://dashscope.aliyuncs.com/api/v1/mcps/WebSearch/mcp";
|
|
3
|
+
export declare const ZHIPU_WEBSEARCH_PRIME_MCP_ENDPOINT = "https://open.bigmodel.cn/api/mcp/web_search_prime/mcp";
|
|
4
|
+
export declare const TAVILY_MCP_ENDPOINT = "https://mcp.tavily.com/mcp/";
|
|
5
|
+
type AuthType = NonNullable<WebSearchMcpConfig['authType']>;
|
|
6
|
+
interface WebSearchProviderProfile {
|
|
7
|
+
id: string;
|
|
8
|
+
aliases: string[];
|
|
9
|
+
endpoint: string;
|
|
10
|
+
toolName?: string;
|
|
11
|
+
authType?: AuthType;
|
|
12
|
+
apiKeyHeader?: string;
|
|
13
|
+
apiKeyQueryParam?: string;
|
|
14
|
+
apiKeyEnvVars: string[];
|
|
15
|
+
matches(config: OpenHorseCLIConfig): boolean;
|
|
16
|
+
note?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ResolvedWebSearchMcpConfig extends WebSearchMcpConfig {
|
|
19
|
+
provider: string;
|
|
20
|
+
endpoint: string;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
note?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the built-in web_search MCP endpoint and auth from the active model
|
|
26
|
+
* provider. Explicit webSearch config always wins; provider profiles are only
|
|
27
|
+
* defaults, so adding a new provider is a small registry change.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveWebSearchMcpConfig(config: OpenHorseCLIConfig): ResolvedWebSearchMcpConfig;
|
|
30
|
+
export declare function getWebSearchMcpErrorSuggestion(config: ResolvedWebSearchMcpConfig): string;
|
|
31
|
+
export declare function listWebSearchProviderProfiles(): Array<Pick<WebSearchProviderProfile, 'id' | 'endpoint' | 'aliases' | 'toolName'>>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=web-search-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search-provider.d.ts","sourceRoot":"","sources":["../../src/services/web-search-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEvE,eAAO,MAAM,8BAA8B,6DAA6D,CAAC;AACzG,eAAO,MAAM,kCAAkC,0DAA0D,CAAC;AAC1G,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AAEjE,KAAK,QAAQ,GAAG,WAAW,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;AAE5D,UAAU,wBAAwB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiFD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,0BAA0B,CAiChG;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,0BAA0B,GAAG,MAAM,CAczF;AAED,wBAAgB,6BAA6B,IAAI,KAAK,CAAC,IAAI,CAAC,wBAAwB,EAAE,IAAI,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC,CAOjI"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TAVILY_MCP_ENDPOINT = exports.ZHIPU_WEBSEARCH_PRIME_MCP_ENDPOINT = exports.BAILIAN_WEBSEARCH_MCP_ENDPOINT = void 0;
|
|
4
|
+
exports.resolveWebSearchMcpConfig = resolveWebSearchMcpConfig;
|
|
5
|
+
exports.getWebSearchMcpErrorSuggestion = getWebSearchMcpErrorSuggestion;
|
|
6
|
+
exports.listWebSearchProviderProfiles = listWebSearchProviderProfiles;
|
|
7
|
+
exports.BAILIAN_WEBSEARCH_MCP_ENDPOINT = 'https://dashscope.aliyuncs.com/api/v1/mcps/WebSearch/mcp';
|
|
8
|
+
exports.ZHIPU_WEBSEARCH_PRIME_MCP_ENDPOINT = 'https://open.bigmodel.cn/api/mcp/web_search_prime/mcp';
|
|
9
|
+
exports.TAVILY_MCP_ENDPOINT = 'https://mcp.tavily.com/mcp/';
|
|
10
|
+
const PROVIDER_PROFILES = [
|
|
11
|
+
{
|
|
12
|
+
id: 'bailian',
|
|
13
|
+
aliases: ['dashscope', 'aliyun', 'alibaba', 'coding-plan', 'coding_plan'],
|
|
14
|
+
endpoint: exports.BAILIAN_WEBSEARCH_MCP_ENDPOINT,
|
|
15
|
+
apiKeyEnvVars: ['OPENHORSE_WEBSEARCH_API_KEY', 'DASHSCOPE_API_KEY'],
|
|
16
|
+
matches(config) {
|
|
17
|
+
const baseUrl = (config.apiBaseUrl || '').toLowerCase();
|
|
18
|
+
return baseUrl.includes('dashscope.aliyuncs.com') || baseUrl.includes('dashscope-intl.aliyuncs.com');
|
|
19
|
+
},
|
|
20
|
+
note: 'Bailian WebSearch MCP. Official docs currently list the dashscope endpoint for Coding Plan tools.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'zhipu',
|
|
24
|
+
aliases: ['glm', 'bigmodel', 'zhipuai', 'web-search-prime'],
|
|
25
|
+
endpoint: exports.ZHIPU_WEBSEARCH_PRIME_MCP_ENDPOINT,
|
|
26
|
+
toolName: 'webSearchPrime',
|
|
27
|
+
apiKeyEnvVars: ['OPENHORSE_WEBSEARCH_API_KEY', 'GLM_API_KEY', 'ZHIPU_API_KEY', 'BIGMODEL_API_KEY'],
|
|
28
|
+
matches(config) {
|
|
29
|
+
const baseUrl = (config.apiBaseUrl || '').toLowerCase();
|
|
30
|
+
const model = (config.model || '').toLowerCase();
|
|
31
|
+
return baseUrl.includes('bigmodel.cn') || (model.startsWith('glm') && !baseUrl.includes('dashscope'));
|
|
32
|
+
},
|
|
33
|
+
note: 'ZhipuAI GLM WebSearch Prime MCP.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'tavily-mcp',
|
|
37
|
+
aliases: [],
|
|
38
|
+
endpoint: exports.TAVILY_MCP_ENDPOINT,
|
|
39
|
+
authType: 'query',
|
|
40
|
+
apiKeyQueryParam: 'tavilyApiKey',
|
|
41
|
+
apiKeyEnvVars: ['OPENHORSE_WEBSEARCH_API_KEY', 'TAVILY_API_KEY'],
|
|
42
|
+
matches() {
|
|
43
|
+
return false;
|
|
44
|
+
},
|
|
45
|
+
note: 'Tavily remote MCP.',
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
function normalizeProvider(value) {
|
|
49
|
+
const normalized = value?.trim().toLowerCase();
|
|
50
|
+
return normalized || undefined;
|
|
51
|
+
}
|
|
52
|
+
function findProfile(provider) {
|
|
53
|
+
const normalized = normalizeProvider(provider);
|
|
54
|
+
if (!normalized || normalized === 'auto')
|
|
55
|
+
return undefined;
|
|
56
|
+
return PROVIDER_PROFILES.find(profile => (profile.id === normalized || profile.aliases.includes(normalized)));
|
|
57
|
+
}
|
|
58
|
+
function inferProfile(config) {
|
|
59
|
+
return PROVIDER_PROFILES.find(profile => profile.matches(config)) || PROVIDER_PROFILES[0];
|
|
60
|
+
}
|
|
61
|
+
function firstEnvValue(names) {
|
|
62
|
+
for (const name of names) {
|
|
63
|
+
const value = process.env[name];
|
|
64
|
+
if (value)
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
function mergeHeaders(profile, explicit) {
|
|
70
|
+
const headers = {
|
|
71
|
+
...(explicit.headers || {}),
|
|
72
|
+
};
|
|
73
|
+
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
74
|
+
}
|
|
75
|
+
function hasExplicitCredential(config) {
|
|
76
|
+
return Boolean(config.apiKey
|
|
77
|
+
|| config.headers?.Authorization
|
|
78
|
+
|| config.headers?.authorization);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the built-in web_search MCP endpoint and auth from the active model
|
|
82
|
+
* provider. Explicit webSearch config always wins; provider profiles are only
|
|
83
|
+
* defaults, so adding a new provider is a small registry change.
|
|
84
|
+
*/
|
|
85
|
+
function resolveWebSearchMcpConfig(config) {
|
|
86
|
+
const explicit = config.webSearch || {};
|
|
87
|
+
const envProvider = process.env.OPENHORSE_WEBSEARCH_PROVIDER ?? process.env.OPENHORSE_WEBSEARCH_MCP_PROVIDER;
|
|
88
|
+
const profile = findProfile(explicit.provider || envProvider) || inferProfile(config);
|
|
89
|
+
const envEndpoint = process.env.OPENHORSE_WEBSEARCH_MCP_ENDPOINT;
|
|
90
|
+
const envToolName = process.env.OPENHORSE_WEBSEARCH_MCP_TOOL;
|
|
91
|
+
const envAuthType = process.env.OPENHORSE_WEBSEARCH_AUTH_TYPE;
|
|
92
|
+
const envApiKeyHeader = process.env.OPENHORSE_WEBSEARCH_API_KEY_HEADER;
|
|
93
|
+
const envApiKeyQueryParam = process.env.OPENHORSE_WEBSEARCH_API_KEY_QUERY_PARAM;
|
|
94
|
+
const providerApiKey = firstEnvValue(profile.apiKeyEnvVars);
|
|
95
|
+
const configuredApiKey = config.apiKey || process.env.OPENHORSE_API_KEY;
|
|
96
|
+
const authType = (explicit.authType
|
|
97
|
+
|| (envAuthType === 'bearer' || envAuthType === 'header' || envAuthType === 'query' || envAuthType === 'none'
|
|
98
|
+
? envAuthType
|
|
99
|
+
: undefined)
|
|
100
|
+
|| profile.authType);
|
|
101
|
+
return {
|
|
102
|
+
provider: profile.id,
|
|
103
|
+
endpoint: explicit.endpoint || envEndpoint || profile.endpoint,
|
|
104
|
+
apiKey: explicit.apiKey || providerApiKey || (hasExplicitCredential(explicit) ? undefined : configuredApiKey),
|
|
105
|
+
toolName: explicit.toolName || envToolName || profile.toolName,
|
|
106
|
+
timeoutMs: explicit.timeoutMs,
|
|
107
|
+
authType,
|
|
108
|
+
apiKeyHeader: explicit.apiKeyHeader || envApiKeyHeader || profile.apiKeyHeader,
|
|
109
|
+
apiKeyQueryParam: explicit.apiKeyQueryParam || envApiKeyQueryParam || profile.apiKeyQueryParam,
|
|
110
|
+
headers: mergeHeaders(profile, explicit),
|
|
111
|
+
note: profile.note,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function getWebSearchMcpErrorSuggestion(config) {
|
|
115
|
+
const provider = config.provider;
|
|
116
|
+
const keyHint = (() => {
|
|
117
|
+
if (provider === 'bailian')
|
|
118
|
+
return 'DASHSCOPE_API_KEY, OPENHORSE_WEBSEARCH_API_KEY, or the configured OpenHorse apiKey';
|
|
119
|
+
if (provider === 'zhipu')
|
|
120
|
+
return 'GLM_API_KEY/ZHIPU_API_KEY/BIGMODEL_API_KEY or OPENHORSE_WEBSEARCH_API_KEY';
|
|
121
|
+
if (provider === 'tavily-mcp')
|
|
122
|
+
return 'TAVILY_API_KEY or OPENHORSE_WEBSEARCH_API_KEY';
|
|
123
|
+
return 'OPENHORSE_WEBSEARCH_API_KEY or the configured OpenHorse apiKey';
|
|
124
|
+
})();
|
|
125
|
+
return [
|
|
126
|
+
`Resolved WebSearch provider "${provider}" to ${config.endpoint}.`,
|
|
127
|
+
`OpenHorse uses ${keyHint} automatically unless webSearch.apiKey/headers override it.`,
|
|
128
|
+
'If this endpoint rejects the key, set webSearch.provider/endpoint/apiKey explicitly for that provider.',
|
|
129
|
+
].join(' ');
|
|
130
|
+
}
|
|
131
|
+
function listWebSearchProviderProfiles() {
|
|
132
|
+
return PROVIDER_PROFILES.map(({ id, endpoint, aliases, toolName }) => ({
|
|
133
|
+
id,
|
|
134
|
+
endpoint,
|
|
135
|
+
aliases,
|
|
136
|
+
toolName,
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=web-search-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search-provider.js","sourceRoot":"","sources":["../../src/services/web-search-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/web.d.ts
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* openhorse - Web Tools
|
|
3
3
|
*
|
|
4
4
|
* WebFetch: Fetch URL content and process with prompt
|
|
5
|
-
* WebSearch:
|
|
5
|
+
* WebSearch: delegate search to provider MCP service
|
|
6
6
|
*
|
|
7
|
-
* v0.1.11: 工具失败透明反馈 - 搜索失败时告知用户失败源、切换后的源、重试次数
|
|
8
7
|
* Issue #32 #3.7: SSRF 拦截 - 拒绝访问内网地址 + Content-Length 上限
|
|
9
8
|
*/
|
|
10
9
|
import { type OpenHorseTool } from '../framework/tool';
|
|
11
10
|
/** Clear the fetch cache (test helper / debugging) */
|
|
12
11
|
export declare function clearWebFetchCache(): void;
|
|
13
12
|
export declare const webFetchTool: OpenHorseTool;
|
|
13
|
+
export declare function resetWebSearchMcpClientForTests(): void;
|
|
14
14
|
export declare const webSearchTool: OpenHorseTool;
|
|
15
15
|
export declare const WEB_TOOLS: OpenHorseTool[];
|
|
16
16
|
//# sourceMappingURL=web.d.ts.map
|
package/dist/tools/web.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/tools/web.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/tools/web.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoSlE,sDAAsD;AACtD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AA0BD,eAAO,MAAM,YAAY,EAAE,aA2GzB,CAAC;AAkCH,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED,eAAO,MAAM,aAAa,EAAE,aA4G1B,CAAC;AAMH,eAAO,MAAM,SAAS,EAAE,aAAa,EAAkC,CAAC"}
|