@klarkxy/dsh-web-search-manager 0.2.5 → 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/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["MAX_RESPONSE_BYTES","registerHostRpc","registerSharedHostRpc","registerHostRpc"],"sources":["../src/jina-fetch.ts","../src/provider-error.ts","../src/search-engine.ts","../src/http-json.ts","../src/rest-search.ts","../src/tavily.ts","../src/native-providers.ts","../src/web-registry.ts","../src/builtins.ts","../src/host-rpc.ts","../src/manager.ts","../src/storage.ts","../src/index.ts"],"sourcesContent":["import { isIP } from 'node:net'\nimport type { WebFetchProvider, WebFetchRequest, WebFetchResult } from '@deepseek-ai/dsh-web'\n\nexport interface JinaFirstFetchOptions {\n readonly reader: WebFetchProvider\n readonly direct: WebFetchProvider\n readonly readerTimeoutMs: number\n}\n\n/** Do not send obvious local addresses, credentials, or nested Reader URLs to a third party. */\nfunction readerUrl(value: string): string | undefined {\n try {\n const url = new URL(value)\n const host = url.hostname.replace(/^\\[|\\]$/g, '').replace(/\\.$/, '').toLowerCase()\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password\n || isIP(host) || !host.includes('.') || host === 'r.jina.ai'\n || /\\.(?:localhost|local|internal|lan|home|test|invalid)$/.test(host)) return undefined\n return `https://r.jina.ai/${url.href}`\n } catch { return undefined }\n}\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? value as Record<string, unknown> : undefined\n}\n\n/** Accept Reader's text envelope or negotiated JSON, but not error/empty responses. */\nfunction readerContent(result: WebFetchResult): string | undefined {\n if (result.statusCode < 200 || result.statusCode >= 300 || result.body.kind !== 'text') return undefined\n const content = result.body.content\n if (content.trimStart().startsWith('{')) {\n try {\n const envelope = object(JSON.parse(content))\n if (!envelope || (envelope.code !== undefined && envelope.code !== 200)) return undefined\n const page = object(envelope.data) ?? envelope\n return typeof page.content === 'string' && page.content.trim() && !page.warning\n ? page.content : undefined\n } catch { return undefined }\n }\n const marker = /^Markdown Content:[\\t ]*\\r?$/m.exec(content)\n if (!marker || /^Warning:/im.test(content.slice(0, marker.index))) return undefined\n return content.slice(marker.index + marker[0].length).trim() ? content : undefined\n}\n\n/** Bound the Reader stage even if a provider fails to honour its cooperative signal. */\nasync function readWithTimeout(\n read: (signal: AbortSignal) => Promise<WebFetchResult>, timeoutMs: number, parent?: AbortSignal,\n): Promise<WebFetchResult> {\n parent?.throwIfAborted()\n const controller = new AbortController()\n const signal = parent ? AbortSignal.any([parent, controller.signal]) : controller.signal\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n let off = () => {}\n const aborted = new Promise<never>((_, reject) => {\n const onAbort = () => reject(signal.reason)\n signal.addEventListener('abort', onAbort, { once: true })\n off = () => signal.removeEventListener('abort', onAbort)\n })\n try {\n return await Promise.race([\n Promise.resolve().then(() => { signal.throwIfAborted(); return read(signal) }),\n aborted,\n ])\n } finally {\n clearTimeout(timer)\n off()\n }\n}\n\n/** One managed fetch route: anonymous Jina Reader first, existing safe HTTP transport second. */\nexport class JinaFirstFetchProvider implements WebFetchProvider {\n // Preserve stored settings, environment overrides, and the managed registry identity.\n readonly id = 'http'\n private readonly options: JinaFirstFetchOptions\n\n constructor(options: JinaFirstFetchOptions) {\n if (!Number.isInteger(options.readerTimeoutMs) || options.readerTimeoutMs < 1\n || options.readerTimeoutMs > 2_147_483_647) throw new Error('Invalid Reader timeout')\n this.options = options\n }\n\n available(): boolean { return this.options.direct.available() }\n\n async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult> {\n signal?.throwIfAborted()\n const url = readerUrl(request.url)\n if (url && this.options.reader.available()) {\n try {\n // Only the URL is forwarded. No account, API key, cookie, or caller headers are added.\n const result = await readWithTimeout(\n combined => this.options.reader.fetch({ url }, combined), this.options.readerTimeoutMs, signal,\n )\n signal?.throwIfAborted()\n const content = readerContent(result)\n if (content !== undefined) return { ...result, url: request.url, body: { kind: 'text', content } }\n } catch {\n // A Reader timeout/failure permits fallback; caller cancellation or the total deadline does not.\n signal?.throwIfAborted()\n }\n }\n signal?.throwIfAborted()\n // Keep the original request, cancellation/deadline, URL policy, redirects, and error semantics.\n return this.options.direct.fetch(request, signal)\n }\n}\n","import { WebError } from '@deepseek-ai/dsh-web'\n\n/** Preserve diagnostics, removing known credential values and common authentication fields only. */\nexport function redactDescription(text: string, secrets: readonly string[] = []): string {\n let result = text\n for (const secret of secrets.filter(Boolean).sort((a, b) => b.length - a.length)) {\n for (const value of new Set([secret, encodeURIComponent(secret)])) result = result.split(value).join('[REDACTED]')\n }\n result = result\n .replace(/(https?:\\/\\/)[^\\s/@]+@/gi, '$1[REDACTED]@')\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(/([?&](?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|key)=)[^&#\\s]*/gi, '$1[REDACTED]')\n .replace(/([\"']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret|authorization|cookie|set-cookie)[\"']?\\s*[:=]\\s*)(?:\"[^\"]*\"|'[^']*'|[^\\s,;}]+)/gi, '$1[REDACTED]')\n return result.slice(0, 1000)\n}\n\nexport class HttpStatusError extends WebError {\n readonly status: number\n constructor(status: number) {\n const safe = Number.isInteger(status) && status >= 100 && status <= 599 ? status : 0\n super(safe ? `供应商请求失败(HTTP ${safe})。` : '供应商请求失败。', 'WEB_PROVIDER_ERROR')\n this.status = safe\n }\n}\n\n/** Keep upstream code and descriptions, not the error object, stack, response or headers. */\nexport function providerError(error: unknown, secrets: readonly string[] = []): WebError {\n const seen = new Set<unknown>()\n const descriptions: string[] = []\n let code: string | undefined\n let current = error\n for (let depth = 0; depth < 3 && current && typeof current === 'object' && !seen.has(current); depth++) {\n seen.add(current)\n const item = current as { code?: unknown; message?: unknown; description?: unknown; cause?: unknown }\n if (!code && typeof item.code === 'string' && item.code) code = item.code\n const description = typeof item.description === 'string' && item.description.trim() ? item.description : item.message\n if (typeof description === 'string' && description.trim() && !descriptions.includes(description)) descriptions.push(description)\n current = item.cause\n }\n if (typeof error === 'string' && error.trim()) descriptions.push(error)\n return new WebError(\n redactDescription(descriptions.join(';') || '供应商未提供错误描述。', secrets),\n redactDescription(code || 'WEB_PROVIDER_ERROR', secrets),\n )\n}\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { HttpStatusError, providerError } from './provider-error.ts'\n\n/** Keyless `ctx.web` search backend. The model still calls official `web_search`. */\nexport const SEARCH_ENGINE_ID = 'ddg'\nexport const SEARCH_ENGINE_PAGE = 'https://lite.duckduckgo.com/lite/'\nconst MAX_RESPONSE_BYTES = 2_000_000\nconst USER_AGENT = 'Mozilla/5.0 (compatible; dsh-editor-search/1.0)'\n\nexport function searchEngineUrl(query: string, page = SEARCH_ENGINE_PAGE): string {\n const url = new URL(page)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('Invalid search page')\n url.searchParams.set('q', query)\n return url.href\n}\n\nfunction decodeEntities(value: string): string {\n return value\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&nbsp;/g, ' ')\n}\n\nfunction stripTags(value: string): string {\n return value.replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ')\n}\n\nexport function unwrapSearchHref(href: string, pageUrl: string): string | undefined {\n let raw = decodeEntities(href.trim())\n let url: URL\n try { url = new URL(raw, pageUrl) } catch { return }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) return\n const host = url.hostname\n const isDdg = host === 'duckduckgo.com' || host.endsWith('.duckduckgo.com')\n if (isDdg && (url.pathname === '/l/' || url.pathname === '/l')) {\n const nested = url.searchParams.get('uddg') ?? url.searchParams.get('u')\n if (nested) {\n try { url = new URL(nested) } catch { return }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) return\n }\n }\n const resultHost = url.hostname.replace(/^www\\./, '')\n if (resultHost === 'duckduckgo.com' || resultHost.endsWith('.duckduckgo.com')) return\n return url.href\n}\n\nexport function parseSearchEngineHtml(html: string, pageUrl = SEARCH_ENGINE_PAGE): WebSearchSource[] {\n const sources: WebSearchSource[] = []\n const seen = new Set<string>()\n const re = /<a\\b[^>]*href\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')[^>]*>([\\s\\S]*?)<\\/a>/gi\n let match: RegExpExecArray | null\n while ((match = re.exec(html))) {\n const url = unwrapSearchHref(match[1] ?? match[2] ?? '', pageUrl)\n if (!url || seen.has(url)) continue\n seen.add(url)\n const title = decodeEntities(stripTags(match[3] ?? '')).trim().slice(0, 1000)\n sources.push(title ? { url, title } : { url })\n }\n return sources\n}\n\nasync function readText(response: Response, signal?: AbortSignal): Promise<string> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('Missing response')\n let size = 0\n const chunks: Uint8Array[] = []\n try {\n while (true) {\n signal?.throwIfAborted()\n const { value, done } = await reader.read()\n if (done) break\n size += value.length\n if (size > MAX_RESPONSE_BYTES) throw new Error('Response too large')\n chunks.push(value)\n }\n } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n const bytes = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return new TextDecoder().decode(bytes)\n}\n\n/** Adapter for `ctx.web.search`; `dsh-tool-web` still owns the model-facing `web_search` tool. */\nexport class SearchEngineProvider implements WebSearchProvider {\n readonly id = SEARCH_ENGINE_ID\n constructor(private readonly options: { fetch?: typeof fetch } = {}) {}\n available(): boolean { return true }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n try {\n signal?.throwIfAborted()\n const url = searchEngineUrl(request.query.trim())\n const response = await (this.options.fetch ?? fetch)(url, {\n method: 'GET', redirect: 'follow', signal,\n headers: { accept: 'text/html', 'user-agent': USER_AGENT },\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const sources = parseSearchEngineHtml(await readText(response, signal), response.url || SEARCH_ENGINE_PAGE)\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('搜索已取消。', 'WEB_ABORTED')\n throw providerError(error)\n }\n }\n}\n","import type { WebSearchSource } from '@deepseek-ai/dsh-web'\n\nexport const MAX_RESPONSE_BYTES = 2_000_000\n\nexport function record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nexport async function readJSON(response: Response, signal?: AbortSignal): Promise<unknown> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('Missing response')\n let size = 0\n const chunks: Uint8Array[] = []\n try {\n while (true) {\n signal?.throwIfAborted()\n const { value, done } = await reader.read()\n if (done) break\n size += value.length\n if (size > MAX_RESPONSE_BYTES) throw new Error('Response too large')\n chunks.push(value)\n }\n } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n const bytes = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return JSON.parse(new TextDecoder().decode(bytes)) as unknown\n}\n\nexport function httpsEndpoint(base: string, path = ''): string {\n const url = new URL(base)\n if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) throw new Error('Invalid endpoint')\n return `${url.href.replace(/\\/+$/, '')}${path}`\n}\n\nexport function sourceFrom(raw: unknown, urlKey: string, titleKey?: string, snippetKey?: string): WebSearchSource | undefined {\n const row = record(raw)\n if (typeof row?.[urlKey] !== 'string') return\n let url: URL\n try { url = new URL(row[urlKey] as string) } catch { return }\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) return\n const title = titleKey && typeof row[titleKey] === 'string' ? (row[titleKey] as string).slice(0, 1000) : undefined\n const snippet = snippetKey && typeof row[snippetKey] === 'string' ? (row[snippetKey] as string).slice(0, 8000) : undefined\n return { url: url.href, ...(title ? { title } : {}), ...(snippet ? { snippet } : {}) }\n}\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { httpsEndpoint, readJSON, record, sourceFrom } from './http-json.ts'\nimport { HttpStatusError, providerError } from './provider-error.ts'\n\nexport interface RestSearchOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\n\ntype RestSpec = {\n id: string\n fallback: string\n path: string\n method: 'GET' | 'POST'\n headers(apiKey: string): Record<string, string>\n query?: (request: { query: string; count: number }) => Record<string, string>\n body?: (request: { query: string; count: number }) => unknown\n parse(payload: unknown): WebSearchSource[]\n}\n\nfunction createRestSearch(spec: RestSpec): new (options: RestSearchOptions) => WebSearchProvider {\n return class implements WebSearchProvider {\n readonly id = spec.id\n constructor(private readonly options: RestSearchOptions) {}\n available(): boolean {\n try { httpsEndpoint(this.options.baseURL ?? spec.fallback, spec.path); return Boolean(this.options.apiKey.trim()) }\n catch { return false }\n }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!this.available()) throw new WebError(`${spec.id} 配置不可用。`, 'WEB_CREDENTIAL_MISSING')\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n const query = request.query.trim()\n try {\n signal?.throwIfAborted()\n const url = new URL(httpsEndpoint(this.options.baseURL ?? spec.fallback, spec.path))\n for (const [key, value] of Object.entries(spec.query?.({ query, count }) ?? {})) url.searchParams.set(key, value)\n const response = await (this.options.fetch ?? fetch)(url, {\n method: spec.method, redirect: 'error', signal,\n headers: { accept: 'application/json', ...spec.headers(this.options.apiKey) },\n ...(spec.body ? { body: JSON.stringify(spec.body({ query, count })) } : {}),\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const sources = spec.parse(await readJSON(response, signal))\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('搜索已取消。', 'WEB_ABORTED')\n throw providerError(error, [this.options.apiKey])\n }\n }\n }\n}\n\nexport const BraveSearchProvider = createRestSearch({\n id: 'brave', fallback: 'https://api.search.brave.com', path: '/res/v1/web/search', method: 'GET',\n headers: apiKey => ({ 'x-subscription-token': apiKey }),\n query: ({ query, count }) => ({ q: query, count: String(count) }),\n parse(payload) {\n const results = record(record(payload)?.web)?.results\n return Array.isArray(results) ? results.flatMap(row => sourceFrom(row, 'url', 'title', 'description') ?? []) : []\n },\n})\n\nexport const BochaSearchProvider = createRestSearch({\n id: 'bocha', fallback: 'https://api.bochaai.com', path: '/v1/web-search', method: 'POST',\n headers: apiKey => ({ authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, count, freshness: 'noLimit', summary: false }),\n parse(payload) {\n const pages = record(record(record(payload)?.data)?.webPages)?.value\n ?? record(record(payload)?.webPages)?.value\n return Array.isArray(pages) ? pages.flatMap(row => sourceFrom(row, 'url', 'name', 'snippet') ?? []) : []\n },\n})\n\nexport const SerperSearchProvider = createRestSearch({\n id: 'serper', fallback: 'https://google.serper.dev', path: '/search', method: 'POST',\n headers: apiKey => ({ 'x-api-key': apiKey, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ q: query, num: count }),\n parse(payload) {\n const organic = record(payload)?.organic\n return Array.isArray(organic) ? organic.flatMap(row => sourceFrom(row, 'link', 'title', 'snippet') ?? []) : []\n },\n})\n\nexport const FirecrawlSearchProvider = createRestSearch({\n id: 'firecrawl', fallback: 'https://api.firecrawl.dev', path: '/v1/search', method: 'POST',\n headers: apiKey => ({ authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, limit: count }),\n parse(payload) {\n const data = record(payload)?.data\n return Array.isArray(data) ? data.flatMap(row => sourceFrom(row, 'url', 'title', 'description') ?? []) : []\n },\n})\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { HttpStatusError, providerError } from './provider-error.ts'\nimport { httpsEndpoint, readJSON, record, sourceFrom } from './http-json.ts'\nexport interface TavilyOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\n/** Direct REST adapter. No auxiliary LLM, retries, anonymous fallback or auto-depth. */\nexport class TavilySearchProvider implements WebSearchProvider {\n readonly id = 'tavily'\n constructor(private readonly options: TavilyOptions) {}\n available(): boolean {\n try { httpsEndpoint(this.options.baseURL ?? 'https://api.tavily.com', '/search'); return Boolean(this.options.apiKey.trim()) }\n catch { return false }\n }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!this.available()) throw new WebError('Tavily 配置不可用。', 'WEB_CREDENTIAL_MISSING')\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n try {\n signal?.throwIfAborted()\n const response = await (this.options.fetch ?? fetch)(httpsEndpoint(this.options.baseURL ?? 'https://api.tavily.com', '/search'), {\n method: 'POST', redirect: 'error', signal,\n headers: { authorization: `Bearer ${this.options.apiKey}`, 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({\n query: request.query.trim(), max_results: count, search_depth: 'basic', topic: 'general',\n auto_parameters: false, include_answer: false, include_raw_content: false, include_images: false,\n }),\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const payload = record(await readJSON(response, signal))\n if (!Array.isArray(payload?.results)) throw new Error('Invalid response shape')\n const sources: WebSearchSource[] = []\n for (const raw of payload.results) {\n const row = record(raw)\n const source = sourceFrom(row, 'url', 'title', 'content')\n if (!source || !row) continue\n sources.push({\n ...source,\n // Tavily preserves present empty strings; the shared helper omits them.\n ...(row.title === '' ? { title: '' } : {}),\n ...(row.content === '' ? { snippet: '' } : {}),\n ...(typeof row.published_date === 'string' && Number.isFinite(Date.parse(row.published_date))\n ? { publishedAt: new Date(row.published_date).toISOString() } : {}),\n })\n }\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('Tavily 搜索已取消。', 'WEB_ABORTED')\n throw providerError(error, [this.options.apiKey])\n }\n }\n}\n","import { WebError } from '@deepseek-ai/dsh-web'\nimport { WEB_MANAGER_OWNER, providerKey, validateBaseURL,\n type ProviderDescriptor, type ProviderOptions, type WebSettings,\n type SearchProviderFactory, type FetchProviderFactory } from './contracts.ts'\nimport type { WebRegistry } from './web-registry.ts'\nimport { providerError } from './provider-error.ts'\n\nexport interface ProviderConfiguration {\n settings(): WebSettings\n resolveCredential(ref: string): Promise<string | undefined>\n}\nfunction validate(descriptor: ProviderDescriptor): void {\n if (!/^[a-z][a-z0-9-]{0,63}$/.test(descriptor.id) || !descriptor.label.trim()) {\n throw new WebError('供应商标识或名称无效。', 'WEB_INVALID_PROVIDER')\n }\n if (descriptor.credentialRef && !/^[A-Z][A-Z0-9_]{1,127}$/.test(descriptor.credentialRef)) {\n throw new WebError('供应商凭据引用无效。', 'WEB_INVALID_PROVIDER')\n }\n if (descriptor.defaultBaseURL) validateBaseURL(descriptor.defaultBaseURL)\n for (const [value, label] of [[descriptor.signupUrl, '注册地址'], [descriptor.pricingUrl, '费用说明地址']] as const) {\n if (!value) continue\n try {\n const url = new URL(value)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error()\n } catch { throw new WebError(`${label}须为 HTTPS。`, 'WEB_INVALID_PROVIDER') }\n }\n}\nasync function configuredCall<T>(kind: 'search' | 'fetch', descriptor: ProviderDescriptor,\n configuration: ProviderConfiguration, signal: AbortSignal | undefined,\n run: (options: ProviderOptions) => Promise<T>): Promise<T> {\n let apiKey: string | undefined\n try {\n signal?.throwIfAborted()\n apiKey = descriptor.credentialRef ? await configuration.resolveCredential(descriptor.credentialRef) : undefined\n signal?.throwIfAborted()\n if (descriptor.credentialRef && !apiKey?.trim()) throw new WebError('搜索凭据已删除或不可用,请重新配置。', 'WEB_CREDENTIAL_MISSING')\n const settings = configuration.settings()\n return await run({ apiKey, baseURL: settings.endpoints[providerKey(kind, descriptor.id)] ?? descriptor.defaultBaseURL,\n timeoutMs: settings.timeoutMs, maxFetchChars: settings.maxFetchChars })\n } catch (error) { throw providerError(error, apiKey ? [apiKey] : []) }\n}\n/** Bundle-owned adapters register through the same native ctx.web entry as any plugin. */\nexport function registerNativeSearch(web: WebRegistry, configuration: ProviderConfiguration,\n descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void {\n validate(descriptor)\n return web.registerSearchProvider({\n id: descriptor.id,\n dshWebManagement: Object.freeze({ ...descriptor, configurationOwner: WEB_MANAGER_OWNER }),\n available: () => true,\n search: (request, signal) => configuredCall('search', descriptor, configuration, signal, options => {\n const provider = factory(options)\n if (!provider.available()) throw new WebError('供应商配置不可用。', 'WEB_PROVIDER_ERROR')\n return provider.search(request, signal)\n }),\n } as Parameters<WebRegistry['registerSearchProvider']>[0])\n}\nexport function registerNativeFetch(web: WebRegistry, configuration: ProviderConfiguration,\n descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void {\n validate(descriptor)\n return web.registerFetchProvider({\n id: descriptor.id,\n dshWebManagement: Object.freeze({ ...descriptor, configurationOwner: WEB_MANAGER_OWNER }),\n available: () => true,\n fetch: (request, signal) => configuredCall('fetch', descriptor, configuration, signal, options => {\n const provider = factory(options)\n if (!provider.available()) throw new WebError('供应商配置不可用。', 'WEB_PROVIDER_ERROR')\n return provider.fetch(request, signal)\n }),\n } as Parameters<WebRegistry['registerFetchProvider']>[0])\n}\n","import { WebError, type WebSearchProvider, type WebFetchProvider } from '@deepseek-ai/dsh-web'\nimport type { ProviderKind } from './contracts.ts'\n\nexport interface WebRegistry {\n registerSearchProvider(provider: WebSearchProvider): () => void\n registerFetchProvider(provider: WebFetchProvider): () => void\n}\nexport type NativeProvider = WebSearchProvider | WebFetchProvider\ntype Runtime = WebRegistry & {\n searchProviders: Map<string, NativeProvider>\n fetchProviders: Map<string, NativeProvider>\n searchProviderId?: string\n fetchProviderId?: string\n}\nconst owner = Symbol.for('@klarkxy/dsh-web-search-manager/registry-owner')\n\n/** The only private-host boundary. Verified against DSH 0.2.0-rc.2.\n * Keep the actual Maps: Cordis effects capture them for automatic unregistration.\n * Replace this bridge when the host exposes enumeration/selection publicly.\n */\nfunction runtimeOf(web: WebRegistry): Runtime {\n const runtime = web as Runtime\n if (!(runtime.searchProviders instanceof Map) || !(runtime.fetchProviders instanceof Map)\n || !Object.hasOwn(runtime, 'searchProviderId') || !Object.hasOwn(runtime, 'fetchProviderId')) {\n throw new WebError('当前 ctx.web 不支持注册表管理,请使用兼容的 DSH 版本。', 'WEB_REGISTRY_UNSUPPORTED')\n }\n return runtime\n}\nexport function hasWebProvider(web: WebRegistry, kind: ProviderKind, id: string): boolean {\n return runtimeOf(web)[kind === 'search' ? 'searchProviders' : 'fetchProviders'].has(id)\n}\n\nexport function observeWebRegistry(web: WebRegistry, hooks: {\n add(kind: ProviderKind, provider: NativeProvider): NativeProvider\n remove(kind: ProviderKind, id: string): void\n}): () => void {\n const runtime = runtimeOf(web)\n const maps = [runtime.searchProviders, runtime.fetchProviders]\n if (maps.some(map => Object.hasOwn(map, owner))) {\n throw new WebError('ctx.web 已由另一个搜索管理器管理。', 'WEB_REGISTRY_MANAGED')\n }\n const undo: Array<() => void> = []\n try {\n for (const [kind, map] of [['search', maps[0]], ['fetch', maps[1]]] as const) {\n Object.defineProperty(map, owner, { value: true, configurable: true })\n undo.push(() => { delete (map as unknown as Record<symbol, unknown>)[owner] })\n const originals = new Map<string, { original: NativeProvider; wrapped: NativeProvider }>()\n const set = map.set, remove = map.delete, clear = map.clear\n const wrap = (id: string, provider: NativeProvider) => {\n const wrapped = hooks.add(kind, provider)\n originals.set(id, { original: provider, wrapped })\n return wrapped\n }\n undo.push(() => {\n // Never resurrect removed providers or overwrite another owner's mutations.\n for (const [id, row] of originals) if (map.get(id) === row.wrapped) set.call(map, id, row.original)\n })\n for (const [id, provider] of map) set.call(map, id, wrap(id, provider))\n const replacements = {\n set(id: string, provider: NativeProvider) {\n const wrapped = wrap(id, provider)\n set.call(map, id, wrapped)\n return map\n },\n delete(id: string) {\n const removed = remove.call(map, id)\n if (removed) { originals.delete(id); hooks.remove(kind, id) }\n return removed\n },\n clear() {\n const ids = [...map.keys()]\n clear.call(map)\n originals.clear()\n for (const id of ids) hooks.remove(kind, id)\n },\n }\n for (const key of ['set', 'delete', 'clear'] as const) {\n const before = Object.getOwnPropertyDescriptor(map, key)\n Object.defineProperty(map, key, { value: replacements[key], configurable: true, writable: true })\n undo.push(() => {\n if (map[key] !== replacements[key]) return\n if (before) Object.defineProperty(map, key, before)\n else delete (map as unknown as Record<string, unknown>)[key]\n })\n }\n }\n for (const key of ['searchProviderId', 'fetchProviderId'] as const) {\n const before = Object.getOwnPropertyDescriptor(runtime, key)!\n Object.defineProperty(runtime, key, { ...before, value: undefined })\n undo.push(() => {\n if (runtime[key] === undefined) Object.defineProperty(runtime, key, before)\n })\n }\n } catch (error) {\n for (const restore of undo.reverse()) restore()\n throw new WebError('无法接管 ctx.web 注册表,已恢复原状。', 'WEB_REGISTRY_UNSUPPORTED', { cause: error })\n }\n let stopped = false\n return () => {\n if (stopped) return\n stopped = true\n for (const restore of undo.reverse()) restore()\n }\n}\n","import {\n DEEPSEEK_DEFAULT_API_VERSION,\n DEEPSEEK_DEFAULT_BASE_URL,\n DEEPSEEK_DEFAULT_MAX_TOKENS,\n DEEPSEEK_DEFAULT_MAX_USES,\n DEEPSEEK_DEFAULT_MODEL,\n DeepSeekSearchProvider,\n} from '@deepseek-ai/dsh-web-search-deepseek'\nimport { ExaSearchProvider } from '@deepseek-ai/dsh-web-search-exa'\nimport { HttpFetchProvider } from '@deepseek-ai/dsh-web-fetch-http'\nimport { JinaFirstFetchProvider } from './jina-fetch.ts'\nimport { SEARCH_ENGINE_ID, SearchEngineProvider } from './search-engine.ts'\nimport { BochaSearchProvider, BraveSearchProvider, FirecrawlSearchProvider, SerperSearchProvider } from './rest-search.ts'\nimport { TavilySearchProvider } from './tavily.ts'\nimport { registerNativeSearch, registerNativeFetch, type ProviderConfiguration } from './native-providers.ts'\nimport { hasWebProvider, type WebRegistry } from './web-registry.ts'\nimport type { ProviderDescriptor, SearchProviderFactory, FetchProviderFactory } from './contracts.ts'\n\nexport function registerBuiltins(web: WebRegistry, configuration: ProviderConfiguration): () => void {\n const registered: Array<() => void> = []\n const registerSearch = (descriptor: ProviderDescriptor, factory: SearchProviderFactory) => {\n if (descriptor.legacyId && hasWebProvider(web, 'search', descriptor.legacyId)) return () => {}\n if (hasWebProvider(web, 'search', descriptor.id)) return () => {}\n const off = registerNativeSearch(web, configuration, descriptor, factory)\n registered.push(off)\n return off\n }\n const registerFetch = (descriptor: ProviderDescriptor, factory: FetchProviderFactory) => {\n if (descriptor.legacyId && hasWebProvider(web, 'fetch', descriptor.legacyId)) return () => {}\n if (hasWebProvider(web, 'fetch', descriptor.id)) return () => {}\n const off = registerNativeFetch(web, configuration, descriptor, factory)\n registered.push(off)\n return off\n }\n try {\n registerSearch({\n id: SEARCH_ENGINE_ID, label: 'DuckDuckGo', billing: 'none',\n description: '无需注册。默认后端。',\n }, () => new SearchEngineProvider())\n registerSearch({\n id: 'deepseek-managed', legacyId: 'deepseek-official', label: 'DeepSeek 搜索',\n description: '使用已配置的 DeepSeek API Key,可能产生额外搜索费用。',\n defaultBaseURL: DEEPSEEK_DEFAULT_BASE_URL, credentialRef: 'DEEPSEEK_API_KEY',\n credentialShared: true, credentialHint: '与模型设置共用 Key', billing: 'model-and-tools',\n signupUrl: 'https://platform.deepseek.com/api_keys',\n }, options => new DeepSeekSearchProvider(() => ({\n apiKey: options.apiKey, baseURL: options.baseURL ?? DEEPSEEK_DEFAULT_BASE_URL,\n model: DEEPSEEK_DEFAULT_MODEL, apiVersion: DEEPSEEK_DEFAULT_API_VERSION,\n maxTokens: DEEPSEEK_DEFAULT_MAX_TOKENS, maxUses: DEEPSEEK_DEFAULT_MAX_USES,\n })))\n registerSearch({\n id: 'exa', label: 'Exa', description: '独立 Search API。',\n defaultBaseURL: 'https://api.exa.ai', credentialRef: 'DSH_EDITOR_WEB_EXA_API_KEY', billing: 'request',\n signupUrl: 'https://dashboard.exa.ai/api-keys',\n }, options => new ExaSearchProvider({\n apiKey: options.apiKey ?? '', baseURL: options.baseURL ?? 'https://api.exa.ai',\n searchType: 'auto', highlightsPerResult: 1,\n }))\n registerSearch({\n id: 'brave', label: 'Brave', description: 'Brave Search API。',\n defaultBaseURL: 'https://api.search.brave.com', credentialRef: 'DSH_EDITOR_WEB_BRAVE_API_KEY', billing: 'request',\n signupUrl: 'https://api.search.brave.com',\n }, options => new BraveSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'bocha', label: '博查', description: '中文网页搜索 API。',\n defaultBaseURL: 'https://api.bochaai.com', credentialRef: 'DSH_EDITOR_WEB_BOCHA_API_KEY', billing: 'request',\n signupUrl: 'https://open.bochaai.com',\n }, options => new BochaSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'serper', label: 'Serper', description: 'Google 结果的 Search API。',\n defaultBaseURL: 'https://google.serper.dev', credentialRef: 'DSH_EDITOR_WEB_SERPER_API_KEY', billing: 'request',\n signupUrl: 'https://serper.dev',\n }, options => new SerperSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'firecrawl', label: 'Firecrawl', description: '网页搜索与提取 API。',\n defaultBaseURL: 'https://api.firecrawl.dev', credentialRef: 'DSH_EDITOR_WEB_FIRECRAWL_API_KEY', billing: 'request',\n signupUrl: 'https://www.firecrawl.dev',\n }, options => new FirecrawlSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'tavily', label: 'Tavily', defaultBaseURL: 'https://api.tavily.com',\n description: 'Search API;固定 basic 检索,不自动升级搜索深度。',\n credentialRef: 'DSH_EDITOR_WEB_TAVILY_API_KEY', billing: 'request',\n signupUrl: 'https://app.tavily.com',\n }, options => new TavilySearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerFetch({\n id: 'http-managed', legacyId: 'http', label: '网页读取', billing: 'none',\n description: '优先匿名 Jina Reader 读取,失败后本机 HTTP 直连;无需 Key。',\n }, options => {\n const limits = {\n maxResponseBytes: 5_000_000, maxBodyChars: options.maxFetchChars,\n timeoutMs: options.timeoutMs, maxRedirects: 5, userAgent: 'dsh-editor/managed-web',\n }\n const readerTimeoutMs = Math.min(15_000, Math.floor(options.timeoutMs / 2))\n return new JinaFirstFetchProvider({\n // Decode a complete JSON envelope before the manager applies maxFetchChars to its content.\n reader: new HttpFetchProvider({ ...limits, maxBodyChars: limits.maxResponseBytes, timeoutMs: readerTimeoutMs }),\n direct: new HttpFetchProvider(limits),\n readerTimeoutMs,\n })\n })\n } catch (error) { for (const off of registered.reverse()) off(); throw error }\n return () => { for (const off of registered.splice(0).reverse()) off() }\n}\n","import { registerHostRpc as registerSharedHostRpc, type HostRpcContext } from '@klarkxy/dsh-plugin-kit/host-rpc'\nimport type { RpcResult } from './contracts.ts'\n\nexport type { HostRpcContext }\n\n/** Keep the historical transport error text while sharing admission and request handling. */\nexport function registerHostRpc(\n ctx: HostRpcContext,\n channel: string,\n call: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<RpcResult>,\n): () => void {\n return registerSharedHostRpc(ctx, channel, call, {\n errorBody: status => status === 500 ? 'network settings request failed' : undefined,\n })\n}\n","import { WebError, type WebFetchProvider, type WebSearchProvider } from '@deepseek-ai/dsh-web'\nimport { providerError } from './provider-error.ts'\nimport { observeWebRegistry, type WebRegistry, type NativeProvider } from './web-registry.ts'\nimport { registerNativeSearch, registerNativeFetch, type ProviderConfiguration } from './native-providers.ts'\nimport {\n defaultSettings, migrateSearchOrder, pickActiveSearch, providerKey, resolveSearchOrder, validateBaseURL, safeConfigurationUrl,\n type FetchProviderFactory, type ProviderDescriptor, type ProviderKind, type ProviderOptions,\n WEB_MANAGER_OWNER, type SearchProviderFactory, type WebSettings, type WebStatus,\n} from './contracts.ts'\n\nexport type { WebRegistry } from './web-registry.ts'\nexport interface ManagerOptions {\n web: WebRegistry\n initial?: Omit<WebSettings, 'searchOrder'> & { searchOrder?: string[] }\n resolveCredential(ref: string): Promise<string | undefined>\n save(settings: WebSettings): Promise<void>\n}\ntype Entry = {\n descriptor: ProviderDescriptor; kind: ProviderKind; configured: boolean\n calls: number; failures: number; provider: NativeProvider; active: Set<AbortController>\n}\nfunction fail(code: string, message: string): never { throw new WebError(message, code) }\nfunction bounded(value: number, min: number, max: number, label: string): number {\n if (!Number.isInteger(value) || value < min || value > max) fail('WEB_INVALID_CONFIG', `${label}须为 ${min} 至 ${max} 的整数。`)\n return value\n}\n/** Enforce cancellation even when an extension ignores its cooperative signal. */\nasync function abortable<T>(work: () => Promise<T>, signal: AbortSignal): Promise<T> {\n signal.throwIfAborted()\n let off = () => {}\n const aborted = new Promise<never>((_, reject) => {\n const onAbort = () => reject(new WebError('网络请求已取消或超时。', 'WEB_ABORTED'))\n signal.addEventListener('abort', onAbort, { once: true })\n off = () => signal.removeEventListener('abort', onAbort)\n })\n try {\n return await Promise.race([Promise.resolve().then(() => { signal.throwIfAborted(); return work() }), aborted])\n } finally { off() }\n}\n\n/** Manages consent and provider lifecycle. Selection and execution stay in ctx.web. */\nexport class WebSearchManager {\n private settings: WebSettings\n private entries = new Map<string, Entry>()\n private listeners = new Set<() => void>()\n private pending = Promise.resolve()\n private epoch = 0\n private suspended = false\n private disposed = false\n private storageFailed = false\n private refreshRevision = 0\n private detach: () => void\n private legacyRegistrations = new Set<() => void>()\n\n constructor(private readonly options: ManagerOptions) {\n const initial = structuredClone(options.initial ?? defaultSettings())\n this.settings = { ...defaultSettings(), ...initial, searchOrder: migrateSearchOrder(initial) }\n this.detach = observeWebRegistry(options.web, {\n add: (kind, provider) => this.discover(kind, provider),\n remove: (kind, id) => {\n const key = providerKey(kind, id)\n const entry = this.entries.get(key)\n if (entry) { this.abort(entry); this.entries.delete(key); this.notify() }\n },\n })\n }\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private notify(): void {\n for (const listener of this.listeners) {\n try { listener() } catch { /* observer failure cannot authorize a request */ }\n }\n }\n private knownSearchIds(): string[] {\n return [...this.entries.values()].filter(entry => entry.kind === 'search').map(entry => entry.descriptor.id)\n }\n private keyed(id: string): boolean {\n return Boolean(this.entries.get(providerKey('search', id))?.descriptor.credentialRef)\n }\n private configured(id: string): boolean {\n const entry = this.entries.get(providerKey('search', id))\n return Boolean(entry && this.ready(entry))\n }\n private ready(entry: Entry): boolean {\n try { return entry.configured && entry.provider.available() }\n catch { return false }\n }\n private searchOrder(settings: WebSettings = this.settings): string[] {\n return resolveSearchOrder(this.knownSearchIds(), settings, id => this.keyed(id))\n }\n private activeSearchId(settings: WebSettings = this.settings): string {\n return pickActiveSearch(this.searchOrder(settings), id => this.configured(id))\n }\n private selected(entry: Entry): boolean {\n if (this.disposed || this.suspended || !this.ready(entry)) return false\n if (this.entries.get(providerKey(entry.kind, entry.descriptor.id)) !== entry) return false\n if (entry.kind === 'fetch') {\n return this.settings.fetchEnabled\n && this.settings.fetchProvider === entry.descriptor.id\n && this.entries.get(providerKey('fetch', entry.descriptor.id)) === entry\n }\n return this.settings.searchEnabled && this.activeSearchId() === entry.descriptor.id\n }\n status(): WebStatus {\n const entries = [...this.entries.values()]\n return {\n settings: structuredClone(this.settings), storageFailed: this.storageFailed,\n searchActive: entries.some(entry => entry.kind === 'search' && this.selected(entry)),\n fetchActive: entries.some(entry => entry.kind === 'fetch' && this.selected(entry)),\n providers: entries.map(entry => ({\n ...entry.descriptor, kind: entry.kind, configured: this.ready(entry),\n configurationOwned: entry.descriptor.configurationOwner === WEB_MANAGER_OWNER,\n baseURL: entry.descriptor.configurationOwner === WEB_MANAGER_OWNER\n ? this.settings.endpoints[providerKey(entry.kind, entry.descriptor.id)] ?? entry.descriptor.defaultBaseURL : undefined,\n calls: entry.calls, failures: entry.failures,\n })).sort((a, b) => providerKey(a.kind, a.id).localeCompare(providerKey(b.kind, b.id))),\n }\n }\n async refresh(): Promise<WebStatus> {\n const epoch = this.epoch\n const revision = ++this.refreshRevision\n await Promise.all([...this.entries.entries()].map(async ([key, entry]) => {\n let configured = true\n if (entry.descriptor.configurationOwner === WEB_MANAGER_OWNER && entry.descriptor.credentialRef) {\n try { configured = Boolean((await this.options.resolveCredential(entry.descriptor.credentialRef))?.trim()) }\n catch { configured = false }\n }\n if (this.disposed || epoch !== this.epoch || revision !== this.refreshRevision || this.entries.get(key) !== entry) return\n if (entry.configured !== configured) {\n entry.configured = configured\n if (!configured) this.abort(entry)\n }\n if (!this.ready(entry)) this.abort(entry)\n }))\n this.notify()\n return this.status()\n }\n private abort(entry?: Entry): void {\n for (const target of entry ? [entry] : this.entries.values()) {\n for (const controller of target.active) controller.abort()\n }\n }\n private discover(kind: ProviderKind, provider: NativeProvider): NativeProvider {\n const key = providerKey(kind, provider.id)\n const old = this.entries.get(key)\n if (old) this.abort(old)\n const metadata = (provider as NativeProvider & { dshWebManagement?: Partial<ProviderDescriptor> }).dshWebManagement\n // Copy only the documented display fields; never serialize provider options or credentials.\n const descriptor: { -readonly [K in keyof ProviderDescriptor]: ProviderDescriptor[K] } = {\n id: provider.id, label: typeof metadata?.label === 'string' && metadata.label ? metadata.label : provider.id,\n description: typeof metadata?.description === 'string' ? metadata.description : '',\n billing: ['none', 'request', 'model-and-tools'].includes(metadata?.billing ?? '') ? metadata!.billing! : 'unknown',\n configurationOwner: typeof metadata?.configurationOwner === 'string' && metadata.configurationOwner ? metadata.configurationOwner : undefined,\n configurationUrl: safeConfigurationUrl(metadata?.configurationUrl),\n }\n for (const field of ['credentialHint', 'pricing', 'defaultBaseURL'] as const) {\n if (typeof metadata?.[field] === 'string') descriptor[field] = metadata[field]\n }\n if (typeof metadata?.credentialRef === 'string' && /^[A-Z][A-Z0-9_]{1,127}$/.test(metadata.credentialRef)) descriptor.credentialRef = metadata.credentialRef\n if (metadata?.credentialShared === true) descriptor.credentialShared = true\n for (const field of ['signupUrl', 'pricingUrl'] as const) {\n try {\n const url = new URL(metadata?.[field] ?? '')\n if (url.protocol === 'https:' && !url.username && !url.password) descriptor[field] = metadata![field]\n } catch { /* unsafe optional links do not hide a valid native provider */ }\n }\n const entry: Entry = { descriptor: Object.freeze(descriptor), kind, provider,\n configured: descriptor.configurationOwner !== WEB_MANAGER_OWNER || !descriptor.credentialRef,\n calls: 0, failures: 0, active: new Set() }\n this.entries.set(key, entry)\n // The bundle's old adapters used official ids. Migrate only their fixed aliases;\n // leave values in storage untouched until an explicit user save.\n const legacy = metadata?.legacyId\n const expectedLegacy = kind === 'search' && provider.id === 'deepseek-managed' ? 'deepseek-official'\n : kind === 'fetch' && provider.id === 'http-managed' ? 'http' : undefined\n if (descriptor.configurationOwner === WEB_MANAGER_OWNER && legacy === expectedLegacy && legacy\n && !this.entries.has(providerKey(kind, legacy))) {\n if (kind === 'search') {\n this.settings.searchOrder = this.settings.searchOrder.map(id => id === legacy ? provider.id : id)\n if (this.settings.searchProvider === legacy) this.settings.searchProvider = provider.id\n } else if (this.settings.fetchProvider === legacy) this.settings.fetchProvider = provider.id\n const legacyKey = providerKey(kind, legacy)\n if (this.settings.endpoints[legacyKey] && !this.settings.endpoints[key]) this.settings.endpoints[key] = this.settings.endpoints[legacyKey]\n }\n void this.refresh()\n if (kind === 'search') {\n const search = provider as WebSearchProvider\n return { id: provider.id, available: () => this.selected(entry), search: (request, signal) => {\n if (typeof request.query !== 'string' || !request.query.trim() || request.query.length > 4000) fail('WEB_INVALID_REQUEST', '查询须为 1 至 4000 字符。')\n const count = Math.min(bounded(request.maxResults ?? this.settings.maxResults, 1, 100, '结果数'), this.settings.maxResults)\n return this.execute(entry, signal, async (_options, combined) => {\n const result = await search.search({ ...request, query: request.query.trim(), maxResults: count }, combined)\n const sources = result.sources.slice(0, count).filter(source => {\n try { const url = new URL(source.url); return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password } catch { return false }\n }).map(source => ({ ...source, title: source.title?.slice(0, 1000), snippet: source.snippet?.slice(0, 8000) }))\n return { ...result, content: result.content?.slice(0, 40_000), sources,\n truncated: result.truncated || result.sources.length > count }\n })\n } }\n }\n const fetch = provider as WebFetchProvider\n return { id: provider.id, available: () => this.selected(entry), fetch: (request, signal) =>\n this.execute(entry, signal, async (options, combined) => {\n const result = await fetch.fetch(request, combined)\n const content = result.body.content.slice(0, options.maxFetchChars)\n return { ...result, body: { ...result.body, content }, truncated: result.truncated || content.length !== result.body.content.length }\n }) }\n }\n /** @deprecated Provider plugins should register directly with ctx.web. */\n registerSearchProvider(descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void {\n return this.legacyRegistration(() => registerNativeSearch(this.options.web, this.providerConfiguration(), descriptor, factory))\n }\n /** @deprecated Provider plugins should register directly with ctx.web. */\n registerFetchProvider(descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void {\n return this.legacyRegistration(() => registerNativeFetch(this.options.web, this.providerConfiguration(), descriptor, factory))\n }\n private providerConfiguration(): ProviderConfiguration {\n return { settings: () => structuredClone(this.settings), resolveCredential: ref => this.options.resolveCredential(ref) }\n }\n private legacyRegistration(register: () => () => void): () => void {\n if (this.disposed) fail('WEB_DISABLED', '网络搜索插件已停止。')\n const unregister = register()\n const off = () => { this.legacyRegistrations.delete(off); unregister() }\n this.legacyRegistrations.add(off)\n return off\n }\n private async execute<T>(entry: Entry, signal: AbortSignal | undefined,\n run: (options: ProviderOptions, signal: AbortSignal) => Promise<T>): Promise<T> {\n if (!this.selected(entry)) fail('WEB_DISABLED', '请在设置 → 网络搜索中配置凭据并启用。')\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), this.settings.timeoutMs)\n const combined = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal\n const epoch = this.epoch\n entry.active.add(controller)\n let started = false\n try {\n if (epoch !== this.epoch || !this.selected(entry)) fail('WEB_DISABLED', '网络访问设置已改变,请重新发起请求。')\n const options = {\n baseURL: this.settings.endpoints[providerKey(entry.kind, entry.descriptor.id)] ?? entry.descriptor.defaultBaseURL,\n timeoutMs: this.settings.timeoutMs, maxFetchChars: this.settings.maxFetchChars,\n }\n started = true\n entry.calls += 1\n const result = await abortable(() => run(options, combined), combined)\n if (epoch !== this.epoch || !this.selected(entry)) fail('WEB_ABORTED', '网络请求已取消。')\n return result\n } catch (error) {\n if (started) entry.failures += 1\n if (error instanceof WebError && error.code === 'WEB_CREDENTIAL_MISSING') {\n entry.configured = false; this.abort(entry); this.notify()\n }\n if (combined.aborted && !(error instanceof WebError && error.code === 'WEB_CREDENTIAL_MISSING')) {\n throw new WebError('网络请求已取消或超时。', 'WEB_ABORTED')\n }\n // Preserve upstream diagnostics, stripping only known credentials and authentication fields.\n const safe = providerError(error)\n throw new WebError(`[${entry.kind}:${entry.descriptor.id}] ${safe.message}`, safe.code)\n } finally {\n clearTimeout(timeout)\n entry.active.delete(controller)\n }\n }\n update(next: Omit<WebSettings, 'revision'>, expectedRevision: number): Promise<WebStatus> {\n const task = this.pending.then(async () => {\n if (this.disposed) fail('WEB_DISABLED', '网络搜索插件已停止。')\n if (expectedRevision !== this.settings.revision) fail('WEB_CONFIG_CONFLICT', '设置已被其他页面修改,请刷新后重试。')\n const proposed: WebSettings = { ...structuredClone(next), revision: expectedRevision + 1 }\n bounded(proposed.maxResults, 1, 20, '结果上限')\n bounded(proposed.maxQueries, 1, 5, '查询上限')\n bounded(proposed.timeoutMs, 1000, 120_000, '超时毫秒数')\n bounded(proposed.maxFetchChars, 1000, 200_000, '正文长度')\n for (const [key, value] of Object.entries(proposed.endpoints)) {\n const entry = this.entries.get(key)\n if (entry && (entry.descriptor.configurationOwner !== WEB_MANAGER_OWNER || !entry.descriptor.defaultBaseURL)\n && value !== this.settings.endpoints[key]) fail('WEB_INVALID_CONFIG', '供应商不支持自定义地址。')\n try { proposed.endpoints[key] = validateBaseURL(value) }\n catch { fail('WEB_INVALID_CONFIG', '供应商地址须为无凭据、无查询参数的 HTTPS 地址。') }\n }\n await this.refresh()\n proposed.searchOrder = [...new Set(proposed.searchOrder)]\n proposed.searchProvider = this.activeSearchId(proposed)\n const activatingSearch = !this.settings.searchEnabled\n || JSON.stringify(proposed.searchOrder) !== JSON.stringify(this.settings.searchOrder)\n if (proposed.searchEnabled && !proposed.searchProvider && activatingSearch) {\n fail('WEB_CREDENTIAL_MISSING', '需选择已安装的供应商并填写有效凭据。')\n }\n if (proposed.fetchEnabled) {\n const entry = this.entries.get(providerKey('fetch', proposed.fetchProvider))\n const activatingFetch = !this.settings.fetchEnabled || proposed.fetchProvider !== this.settings.fetchProvider\n if (activatingFetch && (!entry || !this.ready(entry))) fail('WEB_CREDENTIAL_MISSING', '需选择已安装的供应商并填写有效凭据。')\n }\n this.suspended = true\n this.epoch += 1\n this.abort()\n this.notify()\n try { await this.options.save(proposed) }\n catch {\n this.storageFailed = true\n this.notify()\n fail('WEB_CONFIG_SAVE_FAILED', '保存失败,本次运行已暂停网络访问以防意外联网。')\n }\n this.settings = proposed\n this.storageFailed = false\n this.suspended = false\n this.notify()\n return this.status()\n })\n this.pending = task.then(() => {}, () => {})\n return task\n }\n async dispose(): Promise<void> {\n this.disposed = true\n this.epoch += 1\n this.abort()\n this.notify()\n for (const off of [...this.legacyRegistrations]) off()\n await this.pending\n this.detach()\n this.entries.clear()\n this.listeners.clear()\n }\n}\n","import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\nimport { z } from 'zod'\nimport { migrateSearchOrder } from './contracts.ts'\nexport const settingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n searchEnabled: z.boolean(), fetchEnabled: z.boolean(),\n searchProvider: z.string().max(64), fetchProvider: z.string().max(64),\n searchOrder: z.array(z.string().min(1).max(64)).max(32),\n maxResults: z.number().int().min(1).max(20), maxQueries: z.number().int().min(1).max(5),\n timeoutMs: z.number().int().min(1000).max(120_000), maxFetchChars: z.number().int().min(1000).max(200_000),\n endpoints: z.record(z.string().regex(/^(search|fetch):[a-z][a-z0-9-]{0,63}$/), z.string().max(2048))\n .refine(value => Object.keys(value).length <= 50),\n}).strict()\nexport const updateSchema = z.object({\n expectedRevision: z.number().int().nonnegative(), settings: settingsSchema.omit({ revision: true }),\n}).strict()\nexport const storedSettingsSchema = settingsSchema.extend({\n searchOrder: settingsSchema.shape.searchOrder.optional(),\n}).transform(settings => ({ ...settings, searchOrder: migrateSearchOrder(settings) }))\nexport const webSettingsDomain = defineDomain({\n name: 'dsh_editor_web_search', version: 1,\n tables: { settings: domainTable<string, z.output<typeof storedSettingsSchema>>(storedSettingsSchema) },\n})\n","import type { Context } from '@deepseek-ai/cordis'\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\nimport { WebError } from '@deepseek-ai/dsh-web'\nimport { WEB_PROVIDER_AVAILABILITY_EVENT } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { WEB_SEARCH_RPC_CHANNEL, type RpcResult } from './contracts.ts'\nimport { registerBuiltins } from './builtins.ts'\nimport { registerHostRpc, type HostRpcContext } from './host-rpc.ts'\nimport { WebSearchManager } from './manager.ts'\nimport { updateSchema, webSettingsDomain } from './storage.ts'\nexport { WebSearchManager } from './manager.ts'\nexport type { ProviderDescriptor, ProviderOptions, SearchProviderFactory, FetchProviderFactory } from './contracts.ts'\nexport const name = '@klarkxy/dsh-web-search-manager'\nexport const inject = ['web', 'credentials', 'storageDomain', 'connection', 'webServer'] as const\n\ndeclare module '@deepseek-ai/cordis' { interface Context { webSearchManager: WebSearchManager } }\ntype Host = Context & HostRpcContext & {\n credentials: { resolve(ref: ReturnType<typeof credentialRef>): Promise<{ value: string } | undefined> }\n}\nexport async function apply(ctx: Context): Promise<void> {\n const host = ctx as Host\n const domain = await ctx.storageDomain.open(webSettingsDomain)\n // Own storage before a compatibility check can throw during startup.\n let managed: WebSearchManager | undefined\n ctx.effect(() => async () => { await managed?.dispose(); await domain.close() }, 'web-search-manager.dispose')\n const table = domain.table('settings')\n const manager = managed = new WebSearchManager({\n web: ctx.web, initial: table.get('global'),\n resolveCredential: async ref => (await host.credentials.resolve(credentialRef(ref)))?.value,\n save: settings => table.put('global', settings),\n })\n ctx.provide('webSearchManager', manager)\n ctx.on('credentials/reference-updated', () => { void manager.refresh() })\n ctx.on(WEB_PROVIDER_AVAILABILITY_EVENT, () => { void manager.refresh() })\n ctx.effect(() => registerBuiltins(ctx.web, {\n settings: () => manager.status().settings,\n resolveCredential: async ref => (await host.credentials.resolve(credentialRef(ref)))?.value,\n }), 'web-search-manager.providers')\n ctx.effect(() => registerHostRpc(host, WEB_SEARCH_RPC_CHANNEL, async (endpoint, payload, signal): Promise<RpcResult> => {\n try {\n signal.throwIfAborted()\n if (endpoint === 'status') return { ok: true, value: await manager.refresh() }\n if (endpoint === 'update') {\n const parsed = updateSchema.safeParse(payload)\n if (!parsed.success) return { ok: false, error: { code: 'WEB_INVALID_CONFIG', message: '网络搜索设置格式无效。', details: {} } }\n return { ok: true, value: await manager.update(parsed.data.settings, parsed.data.expectedRevision) }\n }\n if (endpoint === 'test') {\n // Testing is explicit, uses the same authorized registry, and sends no manuscript text.\n const result = await ctx.web.search({ query: 'IANA example domains', maxResults: 1 }, signal)\n return { ok: true, value: { sources: result.sources.length } }\n }\n return { ok: false, error: { code: 'WEB_INVALID_REQUEST', message: '未知操作。', details: {} } }\n } catch (error) {\n return { ok: false, error: {\n code: error instanceof WebError ? error.code : 'WEB_REQUEST_FAILED',\n message: error instanceof WebError ? error.message : '网络设置操作失败,请刷新后重试。', details: {},\n } }\n }\n }), 'web-search-manager.rpc')\n}\ndeclare module '@deepseek-ai/cordis' {\n interface Events {\n /** Repository extension: native providers announce a local availability change. */\n [WEB_PROVIDER_AVAILABILITY_EVENT](kind: 'search' | 'fetch', id: string): void\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["MAX_RESPONSE_BYTES","registerHostRpc","registerSharedHostRpc","registerHostRpc"],"sources":["../src/jina-fetch.ts","../src/provider-error.ts","../src/search-engine.ts","../src/http-json.ts","../src/rest-search.ts","../src/firecrawl-fetch.ts","../src/tavily.ts","../src/native-providers.ts","../src/web-registry.ts","../src/builtins.ts","../src/host-rpc.ts","../src/manager.ts","../src/storage.ts","../src/index.ts"],"sourcesContent":["import { isIP } from 'node:net'\nimport type { WebFetchProvider, WebFetchRequest, WebFetchResult } from '@deepseek-ai/dsh-web'\n\nexport interface JinaFirstFetchOptions {\n readonly reader: WebFetchProvider\n readonly direct: WebFetchProvider\n readonly readerTimeoutMs: number\n}\n\n/** Do not send obvious local addresses, credentials, or nested Reader URLs to a third party. */\nfunction readerUrl(value: string): string | undefined {\n try {\n const url = new URL(value)\n const host = url.hostname.replace(/^\\[|\\]$/g, '').replace(/\\.$/, '').toLowerCase()\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password\n || isIP(host) || !host.includes('.') || host === 'r.jina.ai'\n || /\\.(?:localhost|local|internal|lan|home|test|invalid)$/.test(host)) return undefined\n return `https://r.jina.ai/${url.href}`\n } catch { return undefined }\n}\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? value as Record<string, unknown> : undefined\n}\n\n/** Accept Reader's text envelope or negotiated JSON, but not error/empty responses. */\nfunction readerContent(result: WebFetchResult): string | undefined {\n if (result.statusCode < 200 || result.statusCode >= 300 || result.body.kind !== 'text') return undefined\n const content = result.body.content\n if (content.trimStart().startsWith('{')) {\n try {\n const envelope = object(JSON.parse(content))\n if (!envelope || (envelope.code !== undefined && envelope.code !== 200)) return undefined\n const page = object(envelope.data) ?? envelope\n return typeof page.content === 'string' && page.content.trim() && !page.warning\n ? page.content : undefined\n } catch { return undefined }\n }\n const marker = /^Markdown Content:[\\t ]*\\r?$/m.exec(content)\n if (!marker || /^Warning:/im.test(content.slice(0, marker.index))) return undefined\n return content.slice(marker.index + marker[0].length).trim() ? content : undefined\n}\n\n/** Abort the Reader deadline and wait for its transport to release resources before fallback. */\nasync function readWithTimeout(\n read: (signal: AbortSignal) => Promise<WebFetchResult>, timeoutMs: number, parent?: AbortSignal,\n): Promise<WebFetchResult> {\n parent?.throwIfAborted()\n const controller = new AbortController()\n const signal = parent ? AbortSignal.any([parent, controller.signal]) : controller.signal\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n signal.throwIfAborted()\n const result = await read(signal)\n signal.throwIfAborted()\n return result\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** One managed fetch route: anonymous Jina Reader first, existing safe HTTP transport second. */\nexport class JinaFirstFetchProvider implements WebFetchProvider {\n // Preserve stored settings, environment overrides, and the managed registry identity.\n readonly id = 'http'\n private readonly options: JinaFirstFetchOptions\n\n constructor(options: JinaFirstFetchOptions) {\n if (!Number.isInteger(options.readerTimeoutMs) || options.readerTimeoutMs < 1\n || options.readerTimeoutMs > 2_147_483_647) throw new Error('Invalid Reader timeout')\n this.options = options\n }\n\n available(): boolean { return this.options.direct.available() }\n\n async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult> {\n signal?.throwIfAborted()\n const url = readerUrl(request.url)\n if (url && this.options.reader.available()) {\n try {\n // Only the URL is forwarded. No account, API key, cookie, or caller headers are added.\n const result = await readWithTimeout(\n combined => this.options.reader.fetch({ url }, combined), this.options.readerTimeoutMs, signal,\n )\n signal?.throwIfAborted()\n const content = readerContent(result)\n if (content !== undefined) return { ...result, url: request.url, body: { kind: 'text', content } }\n } catch {\n // A Reader timeout/failure permits fallback; caller cancellation or the total deadline does not.\n signal?.throwIfAborted()\n }\n }\n signal?.throwIfAborted()\n // Keep the original request, cancellation/deadline, URL policy, redirects, and error semantics.\n return this.options.direct.fetch(request, signal)\n }\n}\n","import { WebError } from '@deepseek-ai/dsh-web'\n\n/** Preserve diagnostics, removing known credential values and common authentication fields only. */\nexport function redactDescription(text: string, secrets: readonly string[] = []): string {\n let result = text\n for (const secret of secrets.filter(Boolean).sort((a, b) => b.length - a.length)) {\n for (const value of new Set([secret, encodeURIComponent(secret)])) result = result.split(value).join('[REDACTED]')\n }\n result = result\n .replace(/(https?:\\/\\/)[^\\s/@]+@/gi, '$1[REDACTED]@')\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(/([?&](?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|key)=)[^&#\\s]*/gi, '$1[REDACTED]')\n .replace(/([\"']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret|authorization|cookie|set-cookie)[\"']?\\s*[:=]\\s*)(?:\"[^\"]*\"|'[^']*'|[^\\s,;}]+)/gi, '$1[REDACTED]')\n return result.slice(0, 1000)\n}\n\nexport class HttpStatusError extends WebError {\n readonly status: number\n constructor(status: number) {\n const safe = Number.isInteger(status) && status >= 100 && status <= 599 ? status : 0\n super(safe ? `供应商请求失败(HTTP ${safe})。` : '供应商请求失败。', 'WEB_PROVIDER_ERROR')\n this.status = safe\n }\n}\n\n/** Keep upstream code and descriptions, not the error object, stack, response or headers. */\nexport function providerError(error: unknown, secrets: readonly string[] = []): WebError {\n const seen = new Set<unknown>()\n const descriptions: string[] = []\n let code: string | undefined\n let current = error\n for (let depth = 0; depth < 3 && current && typeof current === 'object' && !seen.has(current); depth++) {\n seen.add(current)\n const item = current as { code?: unknown; message?: unknown; description?: unknown; cause?: unknown }\n if (!code && typeof item.code === 'string' && item.code) code = item.code\n const description = typeof item.description === 'string' && item.description.trim() ? item.description : item.message\n if (typeof description === 'string' && description.trim() && !descriptions.includes(description)) descriptions.push(description)\n current = item.cause\n }\n if (typeof error === 'string' && error.trim()) descriptions.push(error)\n return new WebError(\n redactDescription(descriptions.join(';') || '供应商未提供错误描述。', secrets),\n redactDescription(code || 'WEB_PROVIDER_ERROR', secrets),\n )\n}\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { HttpStatusError, providerError } from './provider-error.ts'\n\n/** Keyless `ctx.web` search backend. The model still calls official `web_search`. */\nexport const SEARCH_ENGINE_ID = 'ddg'\nexport const SEARCH_ENGINE_PAGE = 'https://lite.duckduckgo.com/lite/'\nconst MAX_RESPONSE_BYTES = 2_000_000\nconst USER_AGENT = 'Mozilla/5.0 (compatible; dsh-editor-search/1.0)'\n\nexport function searchEngineUrl(query: string, page = SEARCH_ENGINE_PAGE): string {\n const url = new URL(page)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('Invalid search page')\n url.searchParams.set('q', query)\n return url.href\n}\n\nfunction decodeEntities(value: string): string {\n return value\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&nbsp;/g, ' ')\n}\n\nfunction stripTags(value: string): string {\n return value.replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ')\n}\n\nexport function unwrapSearchHref(href: string, pageUrl: string): string | undefined {\n let raw = decodeEntities(href.trim())\n let url: URL\n try { url = new URL(raw, pageUrl) } catch { return }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) return\n const host = url.hostname\n const isDdg = host === 'duckduckgo.com' || host.endsWith('.duckduckgo.com')\n if (isDdg && (url.pathname === '/l/' || url.pathname === '/l')) {\n const nested = url.searchParams.get('uddg') ?? url.searchParams.get('u')\n if (nested) {\n try { url = new URL(nested) } catch { return }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) return\n }\n }\n const resultHost = url.hostname.replace(/^www\\./, '')\n if (resultHost === 'duckduckgo.com' || resultHost.endsWith('.duckduckgo.com')) return\n return url.href\n}\n\nexport function parseSearchEngineHtml(html: string, pageUrl = SEARCH_ENGINE_PAGE): WebSearchSource[] {\n const sources: WebSearchSource[] = []\n const seen = new Set<string>()\n const re = /<a\\b[^>]*href\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')[^>]*>([\\s\\S]*?)<\\/a>/gi\n let match: RegExpExecArray | null\n while ((match = re.exec(html))) {\n const url = unwrapSearchHref(match[1] ?? match[2] ?? '', pageUrl)\n if (!url || seen.has(url)) continue\n seen.add(url)\n const title = decodeEntities(stripTags(match[3] ?? '')).trim().slice(0, 1000)\n sources.push(title ? { url, title } : { url })\n }\n return sources\n}\n\nasync function readText(response: Response, signal?: AbortSignal): Promise<string> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('Missing response')\n let size = 0\n const chunks: Uint8Array[] = []\n try {\n while (true) {\n signal?.throwIfAborted()\n const { value, done } = await reader.read()\n if (done) break\n size += value.length\n if (size > MAX_RESPONSE_BYTES) throw new Error('Response too large')\n chunks.push(value)\n }\n } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n const bytes = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return new TextDecoder().decode(bytes)\n}\n\n/** Adapter for `ctx.web.search`; `dsh-tool-web` still owns the model-facing `web_search` tool. */\nexport class SearchEngineProvider implements WebSearchProvider {\n readonly id = SEARCH_ENGINE_ID\n constructor(private readonly options: { fetch?: typeof fetch } = {}) {}\n available(): boolean { return true }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n try {\n signal?.throwIfAborted()\n const url = searchEngineUrl(request.query.trim())\n const response = await (this.options.fetch ?? fetch)(url, {\n method: 'GET', redirect: 'follow', signal,\n headers: { accept: 'text/html', 'user-agent': USER_AGENT },\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const sources = parseSearchEngineHtml(await readText(response, signal), response.url || SEARCH_ENGINE_PAGE)\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('搜索已取消。', 'WEB_ABORTED')\n throw providerError(error)\n }\n }\n}\n","import type { WebSearchSource } from '@deepseek-ai/dsh-web'\n\nexport const MAX_RESPONSE_BYTES = 2_000_000\n\nexport function record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nexport async function readJSON(response: Response, signal?: AbortSignal): Promise<unknown> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('Missing response')\n let size = 0\n const chunks: Uint8Array[] = []\n try {\n while (true) {\n signal?.throwIfAborted()\n const { value, done } = await reader.read()\n if (done) break\n size += value.length\n if (size > MAX_RESPONSE_BYTES) throw new Error('Response too large')\n chunks.push(value)\n }\n } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n const bytes = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return JSON.parse(new TextDecoder().decode(bytes)) as unknown\n}\n\nexport function httpsEndpoint(base: string, path = ''): string {\n const url = new URL(base)\n if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) throw new Error('Invalid endpoint')\n return `${url.href.replace(/\\/+$/, '')}${path}`\n}\n\nexport function sourceFrom(raw: unknown, urlKey: string, titleKey?: string, snippetKey?: string): WebSearchSource | undefined {\n const row = record(raw)\n if (typeof row?.[urlKey] !== 'string') return\n let url: URL\n try { url = new URL(row[urlKey] as string) } catch { return }\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) return\n const title = titleKey && typeof row[titleKey] === 'string' ? (row[titleKey] as string).slice(0, 1000) : undefined\n const snippet = snippetKey && typeof row[snippetKey] === 'string' ? (row[snippetKey] as string).slice(0, 8000) : undefined\n return { url: url.href, ...(title ? { title } : {}), ...(snippet ? { snippet } : {}) }\n}\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { httpsEndpoint, readJSON, record, sourceFrom } from './http-json.ts'\nimport { HttpStatusError, providerError } from './provider-error.ts'\n\nexport interface RestSearchOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\n\ntype RestSpec = {\n id: string\n fallback: string\n path: string\n method: 'GET' | 'POST'\n headers(apiKey: string): Record<string, string>\n query?: (request: { query: string; count: number }) => Record<string, string>\n body?: (request: { query: string; count: number }) => unknown\n parse(payload: unknown): WebSearchSource[]\n}\n\nfunction createRestSearch(spec: RestSpec): new (options: RestSearchOptions) => WebSearchProvider {\n return class implements WebSearchProvider {\n readonly id = spec.id\n constructor(private readonly options: RestSearchOptions) {}\n available(): boolean {\n try { httpsEndpoint(this.options.baseURL ?? spec.fallback, spec.path); return Boolean(this.options.apiKey.trim()) }\n catch { return false }\n }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!this.available()) throw new WebError(`${spec.id} 配置不可用。`, 'WEB_CREDENTIAL_MISSING')\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n const query = request.query.trim()\n try {\n signal?.throwIfAborted()\n const url = new URL(httpsEndpoint(this.options.baseURL ?? spec.fallback, spec.path))\n for (const [key, value] of Object.entries(spec.query?.({ query, count }) ?? {})) url.searchParams.set(key, value)\n const response = await (this.options.fetch ?? fetch)(url, {\n method: spec.method, redirect: 'error', signal,\n headers: { accept: 'application/json', ...spec.headers(this.options.apiKey) },\n ...(spec.body ? { body: JSON.stringify(spec.body({ query, count })) } : {}),\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const sources = spec.parse(await readJSON(response, signal))\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('搜索已取消。', 'WEB_ABORTED')\n throw providerError(error, [this.options.apiKey])\n }\n }\n }\n}\n\nexport const BraveSearchProvider = createRestSearch({\n id: 'brave', fallback: 'https://api.search.brave.com', path: '/res/v1/web/search', method: 'GET',\n headers: apiKey => ({ 'x-subscription-token': apiKey }),\n query: ({ query, count }) => ({ q: query, count: String(count) }),\n parse(payload) {\n const results = record(record(payload)?.web)?.results\n return Array.isArray(results) ? results.flatMap(row => sourceFrom(row, 'url', 'title', 'description') ?? []) : []\n },\n})\n\nexport const BochaSearchProvider = createRestSearch({\n id: 'bocha', fallback: 'https://api.bochaai.com', path: '/v1/web-search', method: 'POST',\n headers: apiKey => ({ authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, count, freshness: 'noLimit', summary: false }),\n parse(payload) {\n const pages = record(record(record(payload)?.data)?.webPages)?.value\n ?? record(record(payload)?.webPages)?.value\n return Array.isArray(pages) ? pages.flatMap(row => sourceFrom(row, 'url', 'name', 'snippet') ?? []) : []\n },\n})\n\nexport const SerperSearchProvider = createRestSearch({\n id: 'serper', fallback: 'https://google.serper.dev', path: '/search', method: 'POST',\n headers: apiKey => ({ 'x-api-key': apiKey, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ q: query, num: count }),\n parse(payload) {\n const organic = record(payload)?.organic\n return Array.isArray(organic) ? organic.flatMap(row => sourceFrom(row, 'link', 'title', 'snippet') ?? []) : []\n },\n})\n\n// Official Search APIs return sources directly; no model-generated answer or paid extraction is requested.\n// https://docs.perplexity.ai/api-reference/search-post\nexport const PerplexitySearchProvider = createRestSearch({\n id: 'perplexity', fallback: 'https://api.perplexity.ai', path: '/search', method: 'POST',\n headers: apiKey => ({ authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, max_results: count, search_type: 'web' }),\n parse(payload) {\n const results = record(payload)?.results\n if (!Array.isArray(results)) throw new Error('Perplexity returned no results array.')\n return results.flatMap(row => sourceFrom(row, 'url', 'title', 'snippet') ?? [])\n },\n})\n\n// https://you.com/docs/api-reference/search/v1-search\nexport const YouSearchProvider = createRestSearch({\n id: 'you', fallback: 'https://ydc-index.io', path: '/v1/search', method: 'POST',\n headers: apiKey => ({ 'x-api-key': apiKey, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, count }),\n parse(payload) {\n const results = record(record(payload)?.results)\n if (!results || (!Array.isArray(results.web) && !Array.isArray(results.news))) throw new Error('You.com returned no search results arrays.')\n const rows = [...(Array.isArray(results.web) ? results.web : []), ...(Array.isArray(results.news) ? results.news : [])]\n const seen = new Set<string>()\n return rows.flatMap(raw => {\n const row = record(raw)\n const snippets = Array.isArray(row?.snippets) ? row.snippets.filter((value): value is string => typeof value === 'string').join('\\n') : ''\n const source = sourceFrom({ ...row, snippet: snippets || row?.description }, 'url', 'title', 'snippet')\n if (!source || seen.has(source.url)) return []\n seen.add(source.url)\n return [source]\n })\n },\n})\n\nexport const FirecrawlSearchProvider = createRestSearch({\n id: 'firecrawl', fallback: 'https://api.firecrawl.dev', path: '/v1/search', method: 'POST',\n headers: apiKey => ({ authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' }),\n body: ({ query, count }) => ({ query, limit: count }),\n parse(payload) {\n const data = record(payload)?.data\n return Array.isArray(data) ? data.flatMap(row => sourceFrom(row, 'url', 'title', 'description') ?? []) : []\n },\n})\n","import { WebError, type WebFetchProvider, type WebFetchRequest, type WebFetchResult } from '@deepseek-ai/dsh-web'\nimport { httpsEndpoint, readJSON, record } from './http-json.ts'\nimport { HttpStatusError, providerError } from './provider-error.ts'\nimport type { RestSearchOptions } from './rest-search.ts'\n\nfunction pageURL(value: unknown): string {\n if (typeof value !== 'string') throw new WebError('Firecrawl 未返回最终网页地址。', 'WEB_PROVIDER_ERROR')\n const url = new URL(value)\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) throw new WebError('网页地址无效。', 'WEB_INVALID_URL')\n return url.href\n}\n\n/** https://docs.firecrawl.dev/api-reference/endpoint/scrape — API HTTP status is not the page status. */\nexport class FirecrawlFetchProvider implements WebFetchProvider {\n readonly id = 'firecrawl'\n constructor(private readonly options: RestSearchOptions & { maxFetchChars?: number }) {}\n available(): boolean {\n try { httpsEndpoint(this.options.baseURL ?? 'https://api.firecrawl.dev', '/v2/scrape'); return Boolean(this.options.apiKey.trim()) }\n catch { return false }\n }\n async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult> {\n if (!this.available()) throw new WebError('Firecrawl 配置不可用。', 'WEB_CREDENTIAL_MISSING')\n try {\n signal?.throwIfAborted()\n const url = pageURL(request.url)\n const response = await (this.options.fetch ?? fetch)(httpsEndpoint(this.options.baseURL ?? 'https://api.firecrawl.dev', '/v2/scrape'), {\n method: 'POST', redirect: 'error', signal,\n headers: { accept: 'application/json', authorization: `Bearer ${this.options.apiKey}`, 'content-type': 'application/json' },\n // Markdown only; no LLM cleanup, actions or extra extraction features. Disable TLS bypass.\n body: JSON.stringify({ url, formats: ['markdown'], onlyMainContent: true, skipTlsVerification: false }),\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const payload = record(await readJSON(response, signal))\n signal?.throwIfAborted()\n const data = record(payload?.data), metadata = record(data?.metadata)\n const statusCode = metadata?.statusCode\n if (payload?.success !== true || typeof data?.markdown !== 'string'\n || typeof statusCode !== 'number' || !Number.isInteger(statusCode) || statusCode < 100 || statusCode > 599) {\n throw new WebError('Firecrawl 未返回正文和真实网页状态码。', 'WEB_PROVIDER_ERROR')\n }\n const finalURL = pageURL(metadata?.url)\n const limit = this.options.maxFetchChars ?? 100_000\n return { url: finalURL, statusCode, body: { kind: 'text', content: data.markdown.slice(0, limit) }, truncated: data.markdown.length > limit }\n } catch (error) {\n if (signal?.aborted) throw new WebError('网页读取已取消。', 'WEB_ABORTED')\n throw providerError(error, [this.options.apiKey])\n }\n }\n}\n","import { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport { HttpStatusError, providerError } from './provider-error.ts'\nimport { httpsEndpoint, readJSON, record, sourceFrom } from './http-json.ts'\nexport interface TavilyOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\n/** Direct REST adapter. No auxiliary LLM, retries, anonymous fallback or auto-depth. */\nexport class TavilySearchProvider implements WebSearchProvider {\n readonly id = 'tavily'\n constructor(private readonly options: TavilyOptions) {}\n available(): boolean {\n try { httpsEndpoint(this.options.baseURL ?? 'https://api.tavily.com', '/search'); return Boolean(this.options.apiKey.trim()) }\n catch { return false }\n }\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n if (!this.available()) throw new WebError('Tavily 配置不可用。', 'WEB_CREDENTIAL_MISSING')\n if (!request.query?.trim() || request.query.length > 4000) throw new WebError('查询无效。', 'WEB_INVALID_REQUEST')\n const count = request.maxResults ?? 5\n if (!Number.isInteger(count) || count < 1 || count > 20) throw new WebError('结果数须为 1 至 20。', 'WEB_INVALID_REQUEST')\n try {\n signal?.throwIfAborted()\n const response = await (this.options.fetch ?? fetch)(httpsEndpoint(this.options.baseURL ?? 'https://api.tavily.com', '/search'), {\n method: 'POST', redirect: 'error', signal,\n headers: { authorization: `Bearer ${this.options.apiKey}`, 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({\n query: request.query.trim(), max_results: count, search_depth: 'basic', topic: 'general',\n auto_parameters: false, include_answer: false, include_raw_content: false, include_images: false,\n }),\n })\n if (!response.ok) {\n await response.body?.cancel().catch(() => {})\n throw new HttpStatusError(response.status)\n }\n const payload = record(await readJSON(response, signal))\n if (!Array.isArray(payload?.results)) throw new Error('Invalid response shape')\n const sources: WebSearchSource[] = []\n for (const raw of payload.results) {\n const row = record(raw)\n const source = sourceFrom(row, 'url', 'title', 'content')\n if (!source || !row) continue\n sources.push({\n ...source,\n // Tavily preserves present empty strings; the shared helper omits them.\n ...(row.title === '' ? { title: '' } : {}),\n ...(row.content === '' ? { snippet: '' } : {}),\n ...(typeof row.published_date === 'string' && Number.isFinite(Date.parse(row.published_date))\n ? { publishedAt: new Date(row.published_date).toISOString() } : {}),\n })\n }\n return { sources: sources.slice(0, count), truncated: sources.length > count }\n } catch (error) {\n if (signal?.aborted) throw new WebError('Tavily 搜索已取消。', 'WEB_ABORTED')\n throw providerError(error, [this.options.apiKey])\n }\n }\n}\n","import { WebError } from '@deepseek-ai/dsh-web'\nimport { WEB_MANAGER_OWNER, providerKey, validateBaseURL,\n type ProviderDescriptor, type ProviderOptions, type WebSettings,\n type SearchProviderFactory, type FetchProviderFactory } from './contracts.ts'\nimport type { WebRegistry } from './web-registry.ts'\nimport { providerError } from './provider-error.ts'\n\nexport interface ProviderConfiguration {\n settings(): WebSettings\n resolveCredential(ref: string): Promise<string | undefined>\n}\nfunction validate(descriptor: ProviderDescriptor): void {\n if (!/^[a-z][a-z0-9-]{0,63}$/.test(descriptor.id) || !descriptor.label.trim()) {\n throw new WebError('供应商标识或名称无效。', 'WEB_INVALID_PROVIDER')\n }\n if (descriptor.credentialRef && !/^[A-Z][A-Z0-9_]{1,127}$/.test(descriptor.credentialRef)) {\n throw new WebError('供应商凭据引用无效。', 'WEB_INVALID_PROVIDER')\n }\n if (descriptor.defaultBaseURL) validateBaseURL(descriptor.defaultBaseURL)\n for (const [value, label] of [[descriptor.signupUrl, '注册地址'], [descriptor.pricingUrl, '费用说明地址']] as const) {\n if (!value) continue\n try {\n const url = new URL(value)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error()\n } catch { throw new WebError(`${label}须为 HTTPS。`, 'WEB_INVALID_PROVIDER') }\n }\n}\nasync function configuredCall<T>(kind: 'search' | 'fetch', descriptor: ProviderDescriptor,\n configuration: ProviderConfiguration, signal: AbortSignal | undefined,\n run: (options: ProviderOptions) => Promise<T>): Promise<T> {\n let apiKey: string | undefined\n try {\n signal?.throwIfAborted()\n apiKey = descriptor.credentialRef ? await configuration.resolveCredential(descriptor.credentialRef) : undefined\n signal?.throwIfAborted()\n if (descriptor.credentialRef && !apiKey?.trim()) throw new WebError('搜索凭据已删除或不可用,请重新配置。', 'WEB_CREDENTIAL_MISSING')\n const settings = configuration.settings()\n return await run({ apiKey, baseURL: settings.endpoints[providerKey(kind, descriptor.id)] ?? descriptor.defaultBaseURL,\n timeoutMs: settings.timeoutMs, maxFetchChars: settings.maxFetchChars })\n } catch (error) { throw providerError(error, apiKey ? [apiKey] : []) }\n}\n/** Bundle-owned adapters register through the same native ctx.web entry as any plugin. */\nexport function registerNativeSearch(web: WebRegistry, configuration: ProviderConfiguration,\n descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void {\n validate(descriptor)\n return web.registerSearchProvider({\n id: descriptor.id,\n dshWebManagement: Object.freeze({ ...descriptor, configurationOwner: WEB_MANAGER_OWNER }),\n available: () => true,\n search: (request, signal) => configuredCall('search', descriptor, configuration, signal, options => {\n const provider = factory(options)\n if (!provider.available()) throw new WebError('供应商配置不可用。', 'WEB_PROVIDER_ERROR')\n return provider.search(request, signal)\n }),\n } as Parameters<WebRegistry['registerSearchProvider']>[0])\n}\nexport function registerNativeFetch(web: WebRegistry, configuration: ProviderConfiguration,\n descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void {\n validate(descriptor)\n return web.registerFetchProvider({\n id: descriptor.id,\n dshWebManagement: Object.freeze({ ...descriptor, configurationOwner: WEB_MANAGER_OWNER }),\n available: () => true,\n fetch: (request, signal) => configuredCall('fetch', descriptor, configuration, signal, options => {\n const provider = factory(options)\n if (!provider.available()) throw new WebError('供应商配置不可用。', 'WEB_PROVIDER_ERROR')\n return provider.fetch(request, signal)\n }),\n } as Parameters<WebRegistry['registerFetchProvider']>[0])\n}\n","import { WebError, type WebSearchProvider, type WebFetchProvider } from '@deepseek-ai/dsh-web'\nimport type { ProviderKind } from './contracts.ts'\n\nexport interface WebRegistry {\n registerSearchProvider(provider: WebSearchProvider): () => void\n registerFetchProvider(provider: WebFetchProvider): () => void\n}\nexport type NativeProvider = WebSearchProvider | WebFetchProvider\ntype Runtime = WebRegistry & {\n searchProviders: Map<string, NativeProvider>\n fetchProviders: Map<string, NativeProvider>\n searchProviderId?: string\n fetchProviderId?: string\n searchProviderEnv?: string\n fetchProviderEnv?: string\n config?: {\n searchProvider?: { get?: () => unknown }\n fetchProvider?: { get?: () => unknown }\n }\n}\nconst owner = Symbol.for('@klarkxy/dsh-web-search-manager/registry-owner')\n\n/** The only private-host boundary. Public ctx.web has no selection API.\n * Old hosts snapshot config/env into own searchProviderId/fetchProviderId.\n * Current hosts read config.searchProvider.get() ?? searchProviderEnv on each call\n * (fetch uses the matching pair). Keep the actual Maps: Cordis effects capture them.\n */\nfunction runtimeOf(web: WebRegistry): Runtime {\n const runtime = web as Runtime\n const maps = runtime.searchProviders instanceof Map && runtime.fetchProviders instanceof Map\n const legacy = Object.hasOwn(runtime, 'searchProviderId') && Object.hasOwn(runtime, 'fetchProviderId')\n const current = Object.hasOwn(runtime, 'searchProviderEnv') && Object.hasOwn(runtime, 'fetchProviderEnv')\n && typeof runtime.config?.searchProvider?.get === 'function'\n && typeof runtime.config?.fetchProvider?.get === 'function'\n // Either shape is manageable. A host that still has both is managed too: the call\n // view hides every selection read the two implementations are known to use.\n if (!maps || (!legacy && !current)) {\n throw new WebError('当前 ctx.web 不支持注册表管理,请使用兼容的 DSH 版本。', 'WEB_REGISTRY_UNSUPPORTED')\n }\n return runtime\n}\nexport function hasWebProvider(web: WebRegistry, kind: ProviderKind, id: string): boolean {\n return runtimeOf(web)[kind === 'search' ? 'searchProviders' : 'fetchProviders'].has(id)\n}\n\n/** Hide one volatile selection field without replacing the object the settings UI reads.\n * The host builds these with cosmokit's createVolatile and freezes them, so `get` is an own\n * non-configurable data property that a get trap may not answer differently. Return a standalone\n * facade instead of wrapping the cell: the call path reads one thing from it, config.<field>.get().\n */\nfunction selectionView(field: unknown): unknown {\n if (!field || (typeof field !== 'object' && typeof field !== 'function')) return field\n return Object.freeze({ get: () => undefined })\n}\n/** One call sees no host selection. Config, its volatile source, and env stay on the real runtime.\n * Cordis reads own data properties from the service and ignores an Object.create overlay, so this\n * has to be a get trap. Other reads go to the traced receiver and keep that call's context. Config\n * is proxied over an empty target for the same reason as the cell: a host that froze it would make\n * the two selection fields non-configurable own properties, which no get trap may replace.\n */\nfunction unmanagedView(runtime: Runtime, callReceiver: object): Runtime {\n return new Proxy(runtime, {\n get(target, key, receiver) {\n if (key === 'searchProviderId' || key === 'fetchProviderId' || key === 'searchProviderEnv' || key === 'fetchProviderEnv') return undefined\n if (key === 'config') {\n const config = Reflect.get(target, 'config', target) ?? {}\n return new Proxy({}, {\n get(_view, configKey) {\n if (configKey === 'searchProvider' || configKey === 'fetchProvider') {\n return selectionView(Reflect.get(config, configKey, config))\n }\n return Reflect.get(config, configKey, config)\n },\n })\n }\n if (callReceiver !== target && callReceiver !== receiver) return Reflect.get(callReceiver, key, callReceiver)\n return Reflect.get(target, key, target)\n },\n }) as Runtime\n}\nfunction isThisRuntime(runtime: Runtime, receiver: object): boolean {\n if (receiver === runtime) return true\n try {\n return Reflect.get(receiver, 'searchProviders', receiver) === runtime.searchProviders\n && Reflect.get(receiver, 'fetchProviders', receiver) === runtime.fetchProviders\n } catch { return false }\n}\nfunction installCallView(runtime: Runtime, key: 'search' | 'fetch', undo: Array<() => void>): void {\n // Own property on this service only. The Cordis proxy forwards defineProperty to that target;\n // writing the shared prototype would couple every WebRuntime.\n if (Object.hasOwn(runtime, key)) throw new TypeError(`ctx.web.${key} is already owned by this runtime`)\n let prototype: object | null = Object.getPrototypeOf(runtime)\n while (prototype && !Object.hasOwn(prototype, key)) prototype = Object.getPrototypeOf(prototype)\n const inherited = prototype ? Object.getOwnPropertyDescriptor(prototype, key) : undefined\n if (!inherited || !('value' in inherited) || typeof inherited.value !== 'function') {\n throw new TypeError(`ctx.web.${key} is not a replaceable method`)\n }\n // Close over the prototype method so the wrapper cannot recurse through itself.\n const original = inherited.value as (this: Runtime, ...args: unknown[]) => unknown\n const wrapped = function (this: object, ...args: unknown[]) {\n const receiver = isThisRuntime(runtime, this) ? unmanagedView(runtime, this) : this\n return original.call(receiver as Runtime, ...args)\n }\n Object.defineProperty(runtime, key, { value: wrapped, writable: true, configurable: true, enumerable: false })\n undo.push(() => {\n const current = Object.getOwnPropertyDescriptor(runtime, key)\n // A later owner replaced this property; restoring would discard that change.\n if (current?.value !== wrapped) return\n delete (runtime as unknown as Record<string, unknown>)[key]\n })\n}\n\nexport function observeWebRegistry(web: WebRegistry, hooks: {\n add(kind: ProviderKind, provider: NativeProvider): NativeProvider\n remove(kind: ProviderKind, id: string): void\n}): () => void {\n const runtime = runtimeOf(web)\n const maps = [runtime.searchProviders, runtime.fetchProviders]\n if (maps.some(map => Object.hasOwn(map, owner))) {\n throw new WebError('ctx.web 已由另一个搜索管理器管理。', 'WEB_REGISTRY_MANAGED')\n }\n const undo: Array<() => void> = []\n try {\n for (const [kind, map] of [['search', maps[0]], ['fetch', maps[1]]] as const) {\n Object.defineProperty(map, owner, { value: true, configurable: true })\n undo.push(() => { delete (map as unknown as Record<symbol, unknown>)[owner] })\n const originals = new Map<string, { original: NativeProvider; wrapped: NativeProvider }>()\n const set = map.set, remove = map.delete, clear = map.clear\n const wrap = (id: string, provider: NativeProvider) => {\n const wrapped = hooks.add(kind, provider)\n originals.set(id, { original: provider, wrapped })\n return wrapped\n }\n undo.push(() => {\n // Never resurrect removed providers or overwrite another owner's mutations.\n for (const [id, row] of originals) if (map.get(id) === row.wrapped) set.call(map, id, row.original)\n })\n for (const [id, provider] of map) set.call(map, id, wrap(id, provider))\n const replacements = {\n set(id: string, provider: NativeProvider) {\n const wrapped = wrap(id, provider)\n set.call(map, id, wrapped)\n return map\n },\n delete(id: string) {\n const removed = remove.call(map, id)\n if (removed) { originals.delete(id); hooks.remove(kind, id) }\n return removed\n },\n clear() {\n const ids = [...map.keys()]\n clear.call(map)\n originals.clear()\n for (const id of ids) hooks.remove(kind, id)\n },\n }\n for (const key of ['set', 'delete', 'clear'] as const) {\n const before = Object.getOwnPropertyDescriptor(map, key)\n Object.defineProperty(map, key, { value: replacements[key], configurable: true, writable: true })\n undo.push(() => {\n if (map[key] !== replacements[key]) return\n if (before) Object.defineProperty(map, key, before)\n else delete (map as unknown as Record<string, unknown>)[key]\n })\n }\n }\n installCallView(runtime, 'search', undo)\n installCallView(runtime, 'fetch', undo)\n } catch (error) {\n for (const restore of undo.reverse()) restore()\n throw new WebError('无法接管 ctx.web 注册表,已恢复原状。', 'WEB_REGISTRY_UNSUPPORTED', { cause: error })\n }\n let stopped = false\n return () => {\n if (stopped) return\n stopped = true\n for (const restore of undo.reverse()) restore()\n }\n}\n","import {\n DEEPSEEK_DEFAULT_API_VERSION,\n DEEPSEEK_DEFAULT_BASE_URL,\n DEEPSEEK_DEFAULT_MAX_TOKENS,\n DEEPSEEK_DEFAULT_MAX_USES,\n DEEPSEEK_DEFAULT_MODEL,\n DeepSeekSearchProvider,\n} from '@deepseek-ai/dsh-web-search-deepseek'\nimport { ExaSearchProvider } from '@deepseek-ai/dsh-web-search-exa'\nimport { HttpFetchProvider } from '@deepseek-ai/dsh-web-fetch-http'\nimport { JinaFirstFetchProvider } from './jina-fetch.ts'\nimport { SEARCH_ENGINE_ID, SearchEngineProvider } from './search-engine.ts'\nimport { BochaSearchProvider, BraveSearchProvider, FirecrawlSearchProvider, PerplexitySearchProvider, YouSearchProvider, SerperSearchProvider } from './rest-search.ts'\nimport { FirecrawlFetchProvider } from './firecrawl-fetch.ts'\nimport { TavilySearchProvider } from './tavily.ts'\nimport { registerNativeSearch, registerNativeFetch, type ProviderConfiguration } from './native-providers.ts'\nimport { hasWebProvider, type WebRegistry } from './web-registry.ts'\nimport type { ProviderDescriptor, SearchProviderFactory, FetchProviderFactory } from './contracts.ts'\n\nexport function registerBuiltins(web: WebRegistry, configuration: ProviderConfiguration): () => void {\n const registered: Array<() => void> = []\n const registerSearch = (descriptor: ProviderDescriptor, factory: SearchProviderFactory) => {\n if (descriptor.legacyId && hasWebProvider(web, 'search', descriptor.legacyId)) return () => {}\n if (hasWebProvider(web, 'search', descriptor.id)) return () => {}\n const off = registerNativeSearch(web, configuration, descriptor, factory)\n registered.push(off)\n return off\n }\n const registerFetch = (descriptor: ProviderDescriptor, factory: FetchProviderFactory) => {\n if (descriptor.legacyId && hasWebProvider(web, 'fetch', descriptor.legacyId)) return () => {}\n if (hasWebProvider(web, 'fetch', descriptor.id)) return () => {}\n const off = registerNativeFetch(web, configuration, descriptor, factory)\n registered.push(off)\n return off\n }\n try {\n registerSearch({\n id: SEARCH_ENGINE_ID, label: 'DuckDuckGo', billing: 'none',\n description: '无需注册。默认后端。',\n }, () => new SearchEngineProvider())\n registerSearch({\n id: 'deepseek-managed', legacyId: 'deepseek-official', label: 'DeepSeek 搜索',\n description: '使用已配置的 DeepSeek API Key,可能产生额外搜索费用。',\n defaultBaseURL: DEEPSEEK_DEFAULT_BASE_URL, credentialRef: 'DEEPSEEK_API_KEY',\n credentialShared: true, credentialHint: '与模型设置共用 Key', billing: 'model-and-tools',\n signupUrl: 'https://platform.deepseek.com/api_keys',\n }, options => new DeepSeekSearchProvider(() => ({\n apiKey: options.apiKey, baseURL: options.baseURL ?? DEEPSEEK_DEFAULT_BASE_URL,\n model: DEEPSEEK_DEFAULT_MODEL, apiVersion: DEEPSEEK_DEFAULT_API_VERSION,\n maxTokens: DEEPSEEK_DEFAULT_MAX_TOKENS, maxUses: DEEPSEEK_DEFAULT_MAX_USES,\n })))\n registerSearch({\n id: 'exa', label: 'Exa', description: '独立 Search API。',\n defaultBaseURL: 'https://api.exa.ai', credentialRef: 'DSH_EDITOR_WEB_EXA_API_KEY', billing: 'request',\n signupUrl: 'https://dashboard.exa.ai/api-keys',\n }, options => new ExaSearchProvider({\n apiKey: options.apiKey ?? '', baseURL: options.baseURL ?? 'https://api.exa.ai',\n searchType: 'auto', highlightsPerResult: 1,\n }))\n registerSearch({\n id: 'brave', label: 'Brave', description: 'Brave Search API。',\n defaultBaseURL: 'https://api.search.brave.com', credentialRef: 'DSH_EDITOR_WEB_BRAVE_API_KEY', billing: 'request',\n signupUrl: 'https://api.search.brave.com',\n }, options => new BraveSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'bocha', label: '博查', description: '中文网页搜索 API。',\n defaultBaseURL: 'https://api.bochaai.com', credentialRef: 'DSH_EDITOR_WEB_BOCHA_API_KEY', billing: 'request',\n signupUrl: 'https://open.bochaai.com',\n }, options => new BochaSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'serper', label: 'Serper', description: 'Google 结果的 Search API。',\n defaultBaseURL: 'https://google.serper.dev', credentialRef: 'DSH_EDITOR_WEB_SERPER_API_KEY', billing: 'request',\n signupUrl: 'https://serper.dev',\n }, options => new SerperSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'firecrawl', label: 'Firecrawl', description: '网页搜索与提取 API。',\n defaultBaseURL: 'https://api.firecrawl.dev', credentialRef: 'DSH_EDITOR_WEB_FIRECRAWL_API_KEY', billing: 'request',\n credentialShared: true, credentialHint: '与 Firecrawl 网页读取共用 Key', signupUrl: 'https://www.firecrawl.dev',\n }, options => new FirecrawlSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'tavily', label: 'Tavily', defaultBaseURL: 'https://api.tavily.com',\n description: 'Search API;固定 basic 检索,不自动升级搜索深度。',\n credentialRef: 'DSH_EDITOR_WEB_TAVILY_API_KEY', billing: 'request',\n signupUrl: 'https://app.tavily.com',\n }, options => new TavilySearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'perplexity', label: 'Perplexity', description: 'Search API;返回网页来源,不生成回答。',\n defaultBaseURL: 'https://api.perplexity.ai', credentialRef: 'DSH_EDITOR_WEB_PERPLEXITY_API_KEY', billing: 'request',\n signupUrl: 'https://console.perplexity.ai',\n }, options => new PerplexitySearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerSearch({\n id: 'you', label: 'You.com', description: '网页与新闻搜索;不额外提取全文。',\n defaultBaseURL: 'https://ydc-index.io', credentialRef: 'DSH_EDITOR_WEB_YOU_API_KEY', billing: 'request',\n signupUrl: 'https://you.com/platform',\n }, options => new YouSearchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL }))\n registerFetch({\n id: 'http-managed', legacyId: 'http', label: '网页读取', billing: 'none',\n description: '优先匿名 Jina Reader 读取,失败后本机 HTTP 直连;无需 Key。',\n }, options => {\n const limits = {\n maxResponseBytes: 5_000_000, maxBodyChars: options.maxFetchChars,\n timeoutMs: options.timeoutMs, maxRedirects: 5, userAgent: 'dsh-editor/managed-web',\n }\n const readerTimeoutMs = Math.min(15_000, Math.floor(options.timeoutMs / 2))\n return new JinaFirstFetchProvider({\n // Decode a complete JSON envelope before the manager applies maxFetchChars to its content.\n reader: new HttpFetchProvider({ ...limits, maxBodyChars: limits.maxResponseBytes, timeoutMs: readerTimeoutMs }),\n direct: new HttpFetchProvider(limits),\n readerTimeoutMs,\n })\n })\n registerFetch({\n id: 'firecrawl', label: 'Firecrawl', description: '读取网页 Markdown;与 Firecrawl 搜索共用 Key。',\n defaultBaseURL: 'https://api.firecrawl.dev', credentialRef: 'DSH_EDITOR_WEB_FIRECRAWL_API_KEY', billing: 'request',\n credentialShared: true, credentialHint: '与 Firecrawl 搜索共用 Key', signupUrl: 'https://www.firecrawl.dev',\n }, options => new FirecrawlFetchProvider({ apiKey: options.apiKey ?? '', baseURL: options.baseURL, maxFetchChars: options.maxFetchChars }))\n } catch (error) { for (const off of registered.reverse()) off(); throw error }\n return () => { for (const off of registered.splice(0).reverse()) off() }\n}\n","import { registerHostRpc as registerSharedHostRpc, type HostRpcContext } from '@klarkxy/dsh-plugin-kit/host-rpc'\nimport type { RpcResult } from './contracts.ts'\n\nexport type { HostRpcContext }\n\n/** Keep the historical transport error text while sharing admission and request handling. */\nexport function registerHostRpc(\n ctx: HostRpcContext,\n channel: string,\n call: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<RpcResult>,\n): () => void {\n return registerSharedHostRpc(ctx, channel, call, {\n errorBody: status => status === 500 ? 'network settings request failed' : undefined,\n })\n}\n","import { WebError, type WebFetchProvider, type WebSearchProvider } from '@deepseek-ai/dsh-web'\nimport { providerError } from './provider-error.ts'\nimport { observeWebRegistry, type WebRegistry, type NativeProvider } from './web-registry.ts'\nimport { registerNativeSearch, registerNativeFetch, type ProviderConfiguration } from './native-providers.ts'\nimport {\n defaultSettings, migrateFetchOrder, migrateSearchOrder, pickActiveSearch, providerKey, resolveSearchOrder, validateBaseURL, safeConfigurationUrl,\n type FetchProviderFactory, type ProviderDescriptor, type ProviderKind, type ProviderOptions,\n WEB_MANAGER_OWNER, type SearchProviderFactory, type WebSettings, type WebStatus,\n} from './contracts.ts'\n\nexport type { WebRegistry } from './web-registry.ts'\nexport interface ManagerOptions {\n web: WebRegistry\n initial?: Omit<WebSettings, 'searchOrder' | 'fetchOrder'> & { searchOrder?: string[]; fetchOrder?: string[] }\n resolveCredential(ref: string): Promise<string | undefined>\n save(settings: WebSettings): Promise<void>\n}\ntype Entry = {\n descriptor: ProviderDescriptor; kind: ProviderKind; configured: boolean\n calls: number; failures: number; provider: NativeProvider; active: Set<AbortController>\n}\nfunction fail(code: string, message: string): never { throw new WebError(message, code) }\nfunction bounded(value: number, min: number, max: number, label: string): number {\n if (!Number.isInteger(value) || value < min || value > max) fail('WEB_INVALID_CONFIG', `${label}须为 ${min} 至 ${max} 的整数。`)\n return value\n}\n/** Manages consent and provider lifecycle. Selection and execution stay in ctx.web. */\nexport class WebSearchManager {\n private settings: WebSettings\n private entries = new Map<string, Entry>()\n private listeners = new Set<() => void>()\n private pending = Promise.resolve()\n private epoch = 0\n private suspended = false\n private disposed = false\n private storageFailed = false\n private refreshRevision = 0\n private detach: () => void\n private legacyRegistrations = new Set<() => void>()\n // Keep calls even after their provider is removed from entries.\n private work = new Map<Promise<unknown>, AbortController>()\n\n constructor(private readonly options: ManagerOptions) {\n const initial = structuredClone(options.initial ?? defaultSettings())\n this.settings = { ...defaultSettings(), ...initial,\n searchOrder: migrateSearchOrder(initial), fetchOrder: migrateFetchOrder(initial) }\n this.detach = observeWebRegistry(options.web, {\n add: (kind, provider) => this.discover(kind, provider),\n remove: (kind, id) => {\n const key = providerKey(kind, id)\n const entry = this.entries.get(key)\n if (entry) { this.abort(entry); this.entries.delete(key); this.notify() }\n },\n })\n }\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private notify(): void {\n for (const listener of this.listeners) {\n try { listener() } catch { /* observer failure cannot authorize a request */ }\n }\n }\n private knownSearchIds(): string[] {\n return [...this.entries.values()].filter(entry => entry.kind === 'search').map(entry => entry.descriptor.id)\n }\n private keyed(id: string): boolean {\n return Boolean(this.entries.get(providerKey('search', id))?.descriptor.credentialRef)\n }\n private configured(id: string): boolean {\n const entry = this.entries.get(providerKey('search', id))\n return Boolean(entry && this.ready(entry))\n }\n private ready(entry: Entry): boolean {\n try { return entry.configured && entry.provider.available() }\n catch { return false }\n }\n private searchOrder(settings: WebSettings = this.settings): string[] {\n return resolveSearchOrder(this.knownSearchIds(), settings, id => this.keyed(id))\n }\n private activeSearchId(settings: WebSettings = this.settings): string {\n return pickActiveSearch(this.searchOrder(settings), id => this.configured(id))\n }\n private activeFetchId(settings: WebSettings = this.settings): string {\n return settings.fetchOrder.find(id => {\n const entry = this.entries.get(providerKey('fetch', id))\n return entry !== undefined && this.ready(entry)\n }) ?? ''\n }\n private selected(entry: Entry): boolean {\n if (this.disposed || this.suspended || !this.ready(entry)) return false\n if (this.entries.get(providerKey(entry.kind, entry.descriptor.id)) !== entry) return false\n if (entry.kind === 'fetch') {\n return this.settings.fetchEnabled\n && this.activeFetchId() === entry.descriptor.id\n }\n return this.settings.searchEnabled && this.activeSearchId() === entry.descriptor.id\n }\n status(): WebStatus {\n const entries = [...this.entries.values()]\n return {\n settings: { ...structuredClone(this.settings), fetchProvider: this.activeFetchId() }, storageFailed: this.storageFailed,\n searchActive: entries.some(entry => entry.kind === 'search' && this.selected(entry)),\n fetchActive: entries.some(entry => entry.kind === 'fetch' && this.selected(entry)),\n providers: entries.map(entry => ({\n ...entry.descriptor, kind: entry.kind, configured: this.ready(entry),\n configurationOwned: entry.descriptor.configurationOwner === WEB_MANAGER_OWNER,\n baseURL: entry.descriptor.configurationOwner === WEB_MANAGER_OWNER\n ? this.settings.endpoints[providerKey(entry.kind, entry.descriptor.id)] ?? entry.descriptor.defaultBaseURL : undefined,\n calls: entry.calls, failures: entry.failures,\n })).sort((a, b) => providerKey(a.kind, a.id).localeCompare(providerKey(b.kind, b.id))),\n }\n }\n async refresh(): Promise<WebStatus> {\n const epoch = this.epoch\n const revision = ++this.refreshRevision\n await Promise.all([...this.entries.entries()].map(async ([key, entry]) => {\n let configured = true\n if (entry.descriptor.configurationOwner === WEB_MANAGER_OWNER && entry.descriptor.credentialRef) {\n try { configured = Boolean((await this.options.resolveCredential(entry.descriptor.credentialRef))?.trim()) }\n catch { configured = false }\n }\n if (this.disposed || epoch !== this.epoch || revision !== this.refreshRevision || this.entries.get(key) !== entry) return\n if (entry.configured !== configured) {\n entry.configured = configured\n if (!configured) this.abort(entry)\n }\n if (!this.ready(entry)) this.abort(entry)\n }))\n this.notify()\n return this.status()\n }\n private abort(entry?: Entry): void {\n if (!entry) for (const controller of this.work.values()) controller.abort()\n for (const target of entry ? [entry] : this.entries.values()) {\n for (const controller of target.active) controller.abort()\n }\n }\n private discover(kind: ProviderKind, provider: NativeProvider): NativeProvider {\n const key = providerKey(kind, provider.id)\n const old = this.entries.get(key)\n if (old) this.abort(old)\n const metadata = (provider as NativeProvider & { dshWebManagement?: Partial<ProviderDescriptor> }).dshWebManagement\n // Copy only the documented display fields; never serialize provider options or credentials.\n const descriptor: { -readonly [K in keyof ProviderDescriptor]: ProviderDescriptor[K] } = {\n id: provider.id, label: typeof metadata?.label === 'string' && metadata.label ? metadata.label : provider.id,\n description: typeof metadata?.description === 'string' ? metadata.description : '',\n billing: ['none', 'request', 'model-and-tools'].includes(metadata?.billing ?? '') ? metadata!.billing! : 'unknown',\n configurationOwner: typeof metadata?.configurationOwner === 'string' && metadata.configurationOwner ? metadata.configurationOwner : undefined,\n configurationUrl: safeConfigurationUrl(metadata?.configurationUrl),\n }\n for (const field of ['credentialHint', 'pricing', 'defaultBaseURL'] as const) {\n if (typeof metadata?.[field] === 'string') descriptor[field] = metadata[field]\n }\n if (typeof metadata?.credentialRef === 'string' && /^[A-Z][A-Z0-9_]{1,127}$/.test(metadata.credentialRef)) descriptor.credentialRef = metadata.credentialRef\n if (metadata?.credentialShared === true) descriptor.credentialShared = true\n for (const field of ['signupUrl', 'pricingUrl'] as const) {\n try {\n const url = new URL(metadata?.[field] ?? '')\n if (url.protocol === 'https:' && !url.username && !url.password) descriptor[field] = metadata![field]\n } catch { /* unsafe optional links do not hide a valid native provider */ }\n }\n const entry: Entry = { descriptor: Object.freeze(descriptor), kind, provider,\n configured: descriptor.configurationOwner !== WEB_MANAGER_OWNER || !descriptor.credentialRef,\n calls: 0, failures: 0, active: new Set() }\n this.entries.set(key, entry)\n // The bundle's old adapters used official ids. Migrate only their fixed aliases;\n // leave values in storage untouched until an explicit user save.\n const legacy = metadata?.legacyId\n const expectedLegacy = kind === 'search' && provider.id === 'deepseek-managed' ? 'deepseek-official'\n : kind === 'fetch' && provider.id === 'http-managed' ? 'http' : undefined\n if (descriptor.configurationOwner === WEB_MANAGER_OWNER && legacy === expectedLegacy && legacy\n && !this.entries.has(providerKey(kind, legacy))) {\n if (kind === 'search') {\n this.settings.searchOrder = this.settings.searchOrder.map(id => id === legacy ? provider.id : id)\n if (this.settings.searchProvider === legacy) this.settings.searchProvider = provider.id\n } else {\n this.settings.fetchOrder = this.settings.fetchOrder.map(id => id === legacy ? provider.id : id)\n if (this.settings.fetchProvider === legacy) this.settings.fetchProvider = provider.id\n }\n const legacyKey = providerKey(kind, legacy)\n if (this.settings.endpoints[legacyKey] && !this.settings.endpoints[key]) this.settings.endpoints[key] = this.settings.endpoints[legacyKey]\n }\n void this.refresh()\n if (kind === 'search') {\n const search = provider as WebSearchProvider\n return { id: provider.id, available: () => this.selected(entry), search: (request, signal) => {\n if (typeof request.query !== 'string' || !request.query.trim() || request.query.length > 4000) fail('WEB_INVALID_REQUEST', '查询须为 1 至 4000 字符。')\n const count = Math.min(bounded(request.maxResults ?? this.settings.maxResults, 1, 100, '结果数'), this.settings.maxResults)\n return this.execute(entry, signal, async (_options, combined) => {\n const result = await search.search({ ...request, query: request.query.trim(), maxResults: count }, combined)\n const sources = result.sources.slice(0, count).filter(source => {\n try { const url = new URL(source.url); return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password } catch { return false }\n }).map(source => ({ ...source, title: source.title?.slice(0, 1000), snippet: source.snippet?.slice(0, 8000) }))\n return { ...result, content: result.content?.slice(0, 40_000), sources,\n truncated: result.truncated || result.sources.length > count }\n })\n } }\n }\n const fetch = provider as WebFetchProvider\n return { id: provider.id, available: () => this.selected(entry), fetch: (request, signal) =>\n this.execute(entry, signal, async (options, combined) => {\n const result = await fetch.fetch(request, combined)\n const content = result.body.content.slice(0, options.maxFetchChars)\n return { ...result, body: { ...result.body, content }, truncated: result.truncated || content.length !== result.body.content.length }\n }) }\n }\n /** @deprecated Provider plugins should register directly with ctx.web. */\n registerSearchProvider(descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void {\n return this.legacyRegistration(() => registerNativeSearch(this.options.web, this.providerConfiguration(), descriptor, factory))\n }\n /** @deprecated Provider plugins should register directly with ctx.web. */\n registerFetchProvider(descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void {\n return this.legacyRegistration(() => registerNativeFetch(this.options.web, this.providerConfiguration(), descriptor, factory))\n }\n private providerConfiguration(): ProviderConfiguration {\n return { settings: () => structuredClone(this.settings), resolveCredential: ref => this.options.resolveCredential(ref) }\n }\n private legacyRegistration(register: () => () => void): () => void {\n if (this.disposed) fail('WEB_DISABLED', '网络搜索插件已停止。')\n const unregister = register()\n const off = () => { this.legacyRegistrations.delete(off); unregister() }\n this.legacyRegistrations.add(off)\n return off\n }\n private async execute<T>(entry: Entry, signal: AbortSignal | undefined,\n run: (options: ProviderOptions, signal: AbortSignal) => Promise<T>): Promise<T> {\n if (!this.selected(entry)) fail('WEB_DISABLED', '请在设置 → 网络搜索中配置凭据并启用。')\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), this.settings.timeoutMs)\n const combined = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal\n const epoch = this.epoch\n entry.active.add(controller)\n let started = false\n let work: Promise<T> | undefined\n try {\n if (epoch !== this.epoch || !this.selected(entry)) fail('WEB_DISABLED', '网络访问设置已改变,请重新发起请求。')\n const options = {\n baseURL: this.settings.endpoints[providerKey(entry.kind, entry.descriptor.id)] ?? entry.descriptor.defaultBaseURL,\n timeoutMs: this.settings.timeoutMs, maxFetchChars: this.settings.maxFetchChars,\n }\n started = true\n entry.calls += 1\n // Cancellation is cooperative. Await the actual provider, including its\n // transport/process cleanup; a race would only hide work still running.\n work = Promise.resolve().then(() => { combined.throwIfAborted(); return run(options, combined) })\n this.work.set(work, controller)\n const result = await work\n if (combined.aborted || epoch !== this.epoch || !this.selected(entry)) fail('WEB_ABORTED', '网络请求已取消。')\n return result\n } catch (error) {\n if (started) entry.failures += 1\n if (error instanceof WebError && error.code === 'WEB_CREDENTIAL_MISSING') {\n entry.configured = false; this.abort(entry); this.notify()\n }\n if (combined.aborted && !(error instanceof WebError && error.code === 'WEB_CREDENTIAL_MISSING')) {\n throw new WebError('网络请求已取消或超时。', 'WEB_ABORTED')\n }\n // Preserve upstream diagnostics, stripping only known credentials and authentication fields.\n const safe = providerError(error)\n throw new WebError(`[${entry.kind}:${entry.descriptor.id}] ${safe.message}`, safe.code)\n } finally {\n clearTimeout(timeout)\n entry.active.delete(controller)\n if (work) this.work.delete(work)\n }\n }\n update(next: Omit<WebSettings, 'revision' | 'fetchOrder'> & { fetchOrder?: string[] }, expectedRevision: number): Promise<WebStatus> {\n const task = this.pending.then(async () => {\n if (this.disposed) fail('WEB_DISABLED', '网络搜索插件已停止。')\n if (expectedRevision !== this.settings.revision) fail('WEB_CONFIG_CONFLICT', '设置已被其他页面修改,请刷新后重试。')\n const input = structuredClone(next)\n // Old clients echo the derived single selection on unrelated edits. Preserve the\n // full opt-in list unless they actually change that legacy selection.\n const fetchOrder = input.fetchOrder ?? (input.fetchProvider === this.activeFetchId()\n ? [...this.settings.fetchOrder] : migrateFetchOrder(input))\n const proposed: WebSettings = { ...input, fetchOrder, revision: expectedRevision + 1 }\n bounded(proposed.maxResults, 1, 20, '结果上限')\n bounded(proposed.maxQueries, 1, 5, '查询上限')\n bounded(proposed.timeoutMs, 1000, 120_000, '超时毫秒数')\n bounded(proposed.maxFetchChars, 1000, 200_000, '正文长度')\n for (const [key, value] of Object.entries(proposed.endpoints)) {\n const entry = this.entries.get(key)\n if (entry && (entry.descriptor.configurationOwner !== WEB_MANAGER_OWNER || !entry.descriptor.defaultBaseURL)\n && value !== this.settings.endpoints[key]) fail('WEB_INVALID_CONFIG', '供应商不支持自定义地址。')\n try { proposed.endpoints[key] = validateBaseURL(value) }\n catch { fail('WEB_INVALID_CONFIG', '供应商地址须为无凭据、无查询参数的 HTTPS 地址。') }\n }\n await this.refresh()\n proposed.searchOrder = [...new Set(proposed.searchOrder)]\n proposed.searchProvider = this.activeSearchId(proposed)\n const activatingSearch = !this.settings.searchEnabled\n || JSON.stringify(proposed.searchOrder) !== JSON.stringify(this.settings.searchOrder)\n if (proposed.searchEnabled && !proposed.searchProvider && activatingSearch) {\n fail('WEB_CREDENTIAL_MISSING', '需选择已安装的供应商并填写有效凭据。')\n }\n proposed.fetchOrder = [...new Set(proposed.fetchOrder)]\n proposed.fetchProvider = this.activeFetchId(proposed)\n const activatingFetch = !this.settings.fetchEnabled\n || JSON.stringify(proposed.fetchOrder) !== JSON.stringify(this.settings.fetchOrder)\n if (proposed.fetchEnabled && !proposed.fetchProvider && activatingFetch) {\n fail('WEB_CREDENTIAL_MISSING', '需选择已安装的供应商并填写有效凭据。')\n }\n this.suspended = true\n this.epoch += 1\n this.abort()\n this.notify()\n try { await this.options.save(proposed) }\n catch {\n this.storageFailed = true\n this.notify()\n fail('WEB_CONFIG_SAVE_FAILED', '保存失败,本次运行已暂停网络访问以防意外联网。')\n }\n this.settings = proposed\n this.storageFailed = false\n this.suspended = false\n this.notify()\n return this.status()\n })\n this.pending = task.then(() => {}, () => {})\n return task\n }\n async dispose(): Promise<void> {\n this.disposed = true\n this.epoch += 1\n this.abort()\n this.notify()\n await this.pending\n await Promise.allSettled([...this.work.keys()])\n for (const off of [...this.legacyRegistrations]) off()\n this.detach()\n this.entries.clear()\n this.listeners.clear()\n }\n}\n","import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\nimport { z } from 'zod'\nimport { migrateFetchOrder, migrateSearchOrder } from './contracts.ts'\nexport const settingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n searchEnabled: z.boolean(), fetchEnabled: z.boolean(),\n searchProvider: z.string().max(64), fetchProvider: z.string().max(64),\n searchOrder: z.array(z.string().min(1).max(64)).max(32),\n fetchOrder: z.array(z.string().min(1).max(64)).max(32),\n maxResults: z.number().int().min(1).max(20), maxQueries: z.number().int().min(1).max(5),\n timeoutMs: z.number().int().min(1000).max(120_000), maxFetchChars: z.number().int().min(1000).max(200_000),\n endpoints: z.record(z.string().regex(/^(search|fetch):[a-z][a-z0-9-]{0,63}$/), z.string().max(2048))\n .refine(value => Object.keys(value).length <= 50),\n}).strict()\nexport const updateSchema = z.object({\n expectedRevision: z.number().int().nonnegative(),\n // Keep omission observable so old RPC clients do not erase an existing ordered choice.\n settings: settingsSchema.omit({ revision: true }).extend({ fetchOrder: settingsSchema.shape.fetchOrder.optional() }),\n}).strict()\nexport const storedSettingsSchema = settingsSchema.extend({\n searchOrder: settingsSchema.shape.searchOrder.optional(),\n fetchOrder: settingsSchema.shape.fetchOrder.optional(),\n}).transform(settings => ({ ...settings, searchOrder: migrateSearchOrder(settings), fetchOrder: migrateFetchOrder(settings) }))\nexport const webSettingsDomain = defineDomain({\n name: 'dsh_editor_web_search', version: 1,\n tables: { settings: domainTable<string, z.output<typeof storedSettingsSchema>>(storedSettingsSchema) },\n})\n","import type { Context } from '@deepseek-ai/cordis'\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\nimport { WebError } from '@deepseek-ai/dsh-web'\nimport { WEB_PROVIDER_AVAILABILITY_EVENT } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { WEB_SEARCH_RPC_CHANNEL, type RpcResult } from './contracts.ts'\nimport { registerBuiltins } from './builtins.ts'\nimport { registerHostRpc, type HostRpcContext } from './host-rpc.ts'\nimport { WebSearchManager } from './manager.ts'\nimport { updateSchema, webSettingsDomain } from './storage.ts'\nexport { WebSearchManager } from './manager.ts'\nexport type { ProviderDescriptor, ProviderOptions, SearchProviderFactory, FetchProviderFactory } from './contracts.ts'\nexport const name = '@klarkxy/dsh-web-search-manager'\nexport const inject = ['web', 'credentials', 'storageDomain', 'connection', 'webServer'] as const\n\ndeclare module '@deepseek-ai/cordis' { interface Context { webSearchManager: WebSearchManager } }\ntype Host = Context & HostRpcContext & {\n credentials: { resolve(ref: ReturnType<typeof credentialRef>): Promise<{ value: string } | undefined> }\n}\nexport async function apply(ctx: Context): Promise<void> {\n const host = ctx as Host\n const domain = await ctx.storageDomain.open(webSettingsDomain)\n // Own storage before a compatibility check can throw during startup.\n let managed: WebSearchManager | undefined\n let unregisterBuiltins: (() => void) | undefined\n // Keep explicit teardown ordered; Cordis starts separate async effects concurrently.\n ctx.effect(() => async () => {\n await managed?.dispose()\n unregisterBuiltins?.()\n await domain.close()\n }, 'web-search-manager.dispose')\n const table = domain.table('settings')\n const manager = managed = new WebSearchManager({\n web: ctx.web, initial: table.get('global'),\n resolveCredential: async ref => (await host.credentials.resolve(credentialRef(ref)))?.value,\n save: settings => table.put('global', settings),\n })\n ctx.provide('webSearchManager', manager)\n ctx.on('credentials/reference-updated', () => { void manager.refresh() })\n ctx.on(WEB_PROVIDER_AVAILABILITY_EVENT, () => { void manager.refresh() })\n unregisterBuiltins = registerBuiltins(ctx.web, {\n settings: () => manager.status().settings,\n resolveCredential: async ref => (await host.credentials.resolve(credentialRef(ref)))?.value,\n })\n ctx.effect(() => registerHostRpc(host, WEB_SEARCH_RPC_CHANNEL, async (endpoint, payload, signal): Promise<RpcResult> => {\n try {\n signal.throwIfAborted()\n if (endpoint === 'status') return { ok: true, value: await manager.refresh() }\n if (endpoint === 'update') {\n const parsed = updateSchema.safeParse(payload)\n if (!parsed.success) return { ok: false, error: { code: 'WEB_INVALID_CONFIG', message: '网络搜索设置格式无效。', details: {} } }\n return { ok: true, value: await manager.update(parsed.data.settings, parsed.data.expectedRevision) }\n }\n if (endpoint === 'test') {\n // Testing is explicit, uses the same authorized registry, and sends no manuscript text.\n const result = await ctx.web.search({ query: 'IANA example domains', maxResults: 1 }, signal)\n return { ok: true, value: { sources: result.sources.length } }\n }\n return { ok: false, error: { code: 'WEB_INVALID_REQUEST', message: '未知操作。', details: {} } }\n } catch (error) {\n return { ok: false, error: {\n code: error instanceof WebError ? error.code : 'WEB_REQUEST_FAILED',\n message: error instanceof WebError ? error.message : '网络设置操作失败,请刷新后重试。', details: {},\n } }\n }\n }), 'web-search-manager.rpc')\n}\ndeclare module '@deepseek-ai/cordis' {\n interface Events {\n /** Repository extension: native providers announce a local availability change. */\n [WEB_PROVIDER_AVAILABILITY_EVENT](kind: 'search' | 'fetch', id: string): void\n }\n}\n"],"mappings":"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"}
package/locale/en.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Web Search",
4
- "description": "Manage web search providers and public-page fetching from one settings page."
4
+ "description": "Manage and rank search and page-reading services, including providers from installed plugins, in one settings page."
5
5
  }
6
6
  }
package/locale/zh.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "网页搜索",
4
- "description": "在一个设置页管理搜索供应商与公开页面抓取。"
4
+ "description": "在一个设置页管理和排序多家搜索与网页读取服务,包括已安装插件提供的能力。"
5
5
  }
6
6
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@klarkxy/dsh-web-search-manager",
3
- "version": "0.2.5",
4
- "description": "Web Search: manage web search providers and public-page fetching from one settings page.",
3
+ "version": "0.3.1",
4
+ "description": "Manage and rank search and page-reading services, including providers from installed plugins, in one settings page.",
5
5
  "icon": "./icon.svg",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "type": "module",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@deepseek-ai/dsh-web-search-exa": ">=0.2.0-rc.2",
83
- "@klarkxy/dsh-plugin-kit": "0.3.4",
83
+ "@klarkxy/dsh-plugin-kit": "0.5.0",
84
84
  "zod": "^4.1.5"
85
85
  },
86
86
  "peerDependencies": {
@@ -110,17 +110,20 @@
110
110
  },
111
111
  "@deepseek-ai/dsh-web-search-deepseek": {
112
112
  "optional": true
113
+ },
114
+ "@deepseek-ai/cordis": {
115
+ "optional": true
113
116
  }
114
117
  },
115
118
  "devDependencies": {
116
- "@deepseek-ai/cordis": "4.0.4",
117
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
118
- "@deepseek-ai/dsh-credentials": "0.2.0-rc.2",
119
- "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2",
120
- "@deepseek-ai/dsh-tool-web": "0.2.0-rc.2",
121
- "@deepseek-ai/dsh-web": "0.2.0-rc.2",
122
- "@deepseek-ai/dsh-web-fetch-http": "0.2.0-rc.2",
123
- "@deepseek-ai/dsh-web-search-deepseek": "0.2.0-rc.2",
119
+ "@deepseek-ai/cordis": "4.0.5",
120
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.1",
121
+ "@deepseek-ai/dsh-credentials": "0.2.1-rc.1",
122
+ "@deepseek-ai/dsh-storage-domain": "0.2.1-rc.1",
123
+ "@deepseek-ai/dsh-tool-web": "0.2.1-rc.1",
124
+ "@deepseek-ai/dsh-web": "0.2.1-rc.1",
125
+ "@deepseek-ai/dsh-web-fetch-http": "0.2.1-rc.1",
126
+ "@deepseek-ai/dsh-web-search-deepseek": "0.2.1-rc.1",
124
127
  "@types/react": "18.3.31",
125
128
  "react": "^18.2.0"
126
129
  },
@@ -149,6 +152,6 @@
149
152
  "registry": "https://registry.npmjs.org/"
150
153
  },
151
154
  "dshRelease": {
152
- "contentHash": "3707158a266431f5661fd3d0b203d2699cb7658fd6de343fcac0790064f13daa"
155
+ "contentHash": "b13ef2869d849beeed7fa30c94ddb05a2ec803a59d0d258a098c92c211b8a91f"
153
156
  }
154
157
  }