@klarkxy/dsh-web-search-manager 0.1.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -10
- package/cordis.patch.yml +1 -8
- package/docs/README.zh-CN.md +28 -10
- package/lib/client.inner.cjs +507 -83
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +508 -245
- package/lib/contracts.d.ts +19 -2
- package/lib/contracts.js +13 -1
- package/lib/contracts.js.map +1 -1
- package/lib/index.d.ts +18 -3
- package/lib/index.js +488 -331
- package/lib/index.js.map +1 -1
- package/package.json +23 -22
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["MAX_RESPONSE_BYTES","MAX_RESPONSE_BYTES","record","readJSON","readJSON","record"],"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/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(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/ /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'\nexport interface TavilyOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\nconst MAX_RESPONSE_BYTES = 2_000_000\nfunction endpoint(base: string): 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(/\\/+$/, '')}/search`\n}\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\nasync 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 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 } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n}\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 { endpoint(this.options.baseURL ?? 'https://api.tavily.com'); 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)(endpoint(this.options.baseURL ?? 'https://api.tavily.com'), {\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 if (typeof row?.url !== 'string') continue\n let url: URL\n try { url = new URL(row.url) } catch { continue }\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) continue\n sources.push({\n url: url.href,\n ...(typeof row.title === 'string' ? { title: row.title.slice(0, 1000) } : {}),\n ...(typeof row.content === 'string' ? { snippet: row.content.slice(0, 8000) } : {}),\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 {\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 type { WebSearchManager } from './manager.ts'\n\nexport function registerBuiltins(manager: WebSearchManager): () => void {\n const offEngine = manager.registerSearchProvider({\n id: SEARCH_ENGINE_ID, label: 'DuckDuckGo', billing: 'none',\n description: '无需注册。默认后端。',\n }, () => new SearchEngineProvider())\n const offDeepSeek = manager.registerSearchProvider({\n id: '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 const offExa = manager.registerSearchProvider({\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 const offBrave = manager.registerSearchProvider({\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 const offBocha = manager.registerSearchProvider({\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 const offSerper = manager.registerSearchProvider({\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 const offFirecrawl = manager.registerSearchProvider({\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 const offTavily = manager.registerSearchProvider({\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 const offHttp = manager.registerFetchProvider({\n id: '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 return () => {\n offHttp(); offTavily(); offFirecrawl(); offSerper(); offBocha(); offBrave(); offExa(); offDeepSeek(); offEngine()\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { RpcResult } from './contracts.ts'\nexport interface HostRpcContext {\n webServer: { register(route: { kind: 'prefix'; path: string; handler(req: IncomingMessage, res: ServerResponse): void | Promise<void> }): () => void }\n connection: { requestRejection?: (request: IncomingMessage) => number | undefined }\n}\nexport function registerHostRpc(ctx: HostRpcContext, channel: string,\n call: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<RpcResult>): () => void {\n return ctx.webServer.register({ kind: 'prefix', path: channel, handler: async (req, res) => {\n // Require the host's origin/auth policy. Missing policy must not expose settings.\n if (!ctx.connection.requestRejection) { res.writeHead(503); res.end(); return }\n const rejection = ctx.connection.requestRejection(req)\n if (rejection !== undefined) { res.writeHead(rejection); res.end(); return }\n const pathname = new URL(req.url ?? '/', 'http://dsh.internal').pathname\n const endpoint = pathname.startsWith(`${channel}/`) ? pathname.slice(channel.length + 1) : ''\n if (req.method !== 'POST' || !/^[a-z.]+$/.test(endpoint)) { res.writeHead(404); res.end(); return }\n if (String(req.headers['content-type'] ?? '').split(';')[0]?.trim() !== 'application/json') {\n res.writeHead(415); res.end(); return\n }\n const controller = new AbortController()\n res.on('close', () => { if (!res.writableEnded) controller.abort() })\n try {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += buffer.length\n if (size > 64 * 1024) { res.writeHead(413, { connection: 'close' }); res.end(); req.destroy(); return }\n chunks.push(buffer)\n }\n let request: Record<string, unknown>\n try {\n const parsed: unknown = JSON.parse(Buffer.concat(chunks).toString('utf8'))\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error()\n request = parsed as Record<string, unknown>\n } catch { res.writeHead(400); res.end(); return }\n if (request.type !== 'client-request' || request.method !== endpoint || typeof request.rpcId !== 'string') {\n res.writeHead(400); res.end(); return\n }\n const result = await call(endpoint, request.payload, controller.signal)\n if (!res.destroyed) {\n res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' })\n res.end(JSON.stringify({ type: 'server-response', rpcId: request.rpcId, result }))\n }\n } catch {\n if (!res.destroyed) { res.writeHead(500); res.end('network settings request failed') }\n }\n } })\n}\n","import { WebError, type WebFetchProvider, type WebSearchProvider } from '@deepseek-ai/dsh-web'\nimport { providerError } from './provider-error.ts'\nimport {\n defaultSettings, migrateSearchOrder, pickActiveSearch, providerKey, resolveSearchOrder, validateBaseURL,\n type FetchProviderFactory, type ProviderDescriptor, type ProviderKind, type ProviderOptions,\n type SearchProviderFactory, type WebSettings, type WebStatus,\n} from './contracts.ts'\n\nexport interface WebRegistry {\n registerSearchProvider(provider: WebSearchProvider): () => void\n registerFetchProvider(provider: WebFetchProvider): () => void\n}\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; unregister(): void; 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\n constructor(private readonly options: ManagerOptions) {\n const initial = structuredClone(options.initial ?? defaultSettings())\n this.settings = { ...defaultSettings(), ...initial, searchOrder: migrateSearchOrder(initial) }\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 return Boolean(this.entries.get(providerKey('search', id))?.configured)\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 || !entry.configured) 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: entry.configured,\n baseURL: this.settings.endpoints[providerKey(entry.kind, entry.descriptor.id)] ?? entry.descriptor.defaultBaseURL,\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 await Promise.all([...this.entries.entries()].map(async ([key, entry]) => {\n let configured = !entry.descriptor.credentialRef\n if (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 || this.entries.get(key) !== entry) return\n if (entry.configured !== configured) {\n entry.configured = configured\n if (!configured) this.abort(entry)\n }\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 add(kind: ProviderKind, descriptor: ProviderDescriptor): Entry {\n if (this.disposed) fail('WEB_DISABLED', '网络搜索插件已停止。')\n const key = providerKey(kind, descriptor.id)\n if (!/^[a-z][a-z0-9-]{0,63}$/.test(descriptor.id) || !descriptor.label.trim()) fail('WEB_INVALID_PROVIDER', '供应商标识或名称无效。')\n if (descriptor.credentialRef && !/^[A-Z][A-Z0-9_]{1,127}$/.test(descriptor.credentialRef)) fail('WEB_INVALID_PROVIDER', '供应商凭据引用无效。')\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) fail('WEB_INVALID_PROVIDER', `${label}须为 HTTPS。`)\n } catch { fail('WEB_INVALID_PROVIDER', `${label}须为 HTTPS。`) }\n }\n if (this.entries.has(key)) fail('WEB_DUPLICATE_PROVIDER', '供应商标识已注册。')\n const entry: Entry = {\n descriptor: Object.freeze({ ...descriptor }), kind, configured: !descriptor.credentialRef,\n calls: 0, failures: 0, unregister() {}, active: new Set(),\n }\n this.entries.set(key, entry)\n return entry\n }\n private registration(entry: Entry, register: () => () => void): () => void {\n const key = providerKey(entry.kind, entry.descriptor.id)\n try { entry.unregister = register() }\n catch (error) { this.entries.delete(key); throw error }\n void this.refresh()\n let removed = false\n return () => {\n if (removed) return\n removed = true\n this.abort(entry)\n this.entries.delete(key)\n entry.unregister()\n this.notify()\n }\n }\n registerSearchProvider(descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void {\n const entry = this.add('search', descriptor)\n return this.registration(entry, () => this.options.web.registerSearchProvider({\n id: descriptor.id, available: () => this.selected(entry),\n 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 provider = factory(options)\n if (!provider.available()) fail('WEB_PROVIDER_ERROR', '供应商配置不可用。')\n const result = await provider.search({ 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 }\n registerFetchProvider(descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void {\n const entry = this.add('fetch', descriptor)\n return this.registration(entry, () => this.options.web.registerFetchProvider({\n id: descriptor.id, available: () => this.selected(entry),\n fetch: (request, signal) => this.execute(entry, signal, async (options, combined) => {\n const provider = factory(options)\n if (!provider.available()) fail('WEB_PROVIDER_ERROR', '供应商配置不可用。')\n const result = await provider.fetch(request, combined)\n const content = result.body.content.slice(0, options.maxFetchChars)\n return { ...result, body: { ...result.body, content },\n truncated: result.truncated || content.length !== result.body.content.length }\n }),\n }))\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 apiKey: string | undefined\n try {\n const ref = entry.descriptor.credentialRef\n apiKey = ref ? await abortable(() => this.options.resolveCredential(ref), combined) : undefined\n if (ref && !apiKey?.trim()) {\n entry.configured = false\n this.abort(entry)\n this.notify()\n fail('WEB_CREDENTIAL_MISSING', '搜索凭据已删除或不可用,请重新配置。')\n }\n if (epoch !== this.epoch || !this.selected(entry)) fail('WEB_DISABLED', '网络访问设置已改变,请重新发起请求。')\n const options = {\n apiKey, 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 // Missing credentials abort active calls too; keep that original failure for this call.\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, apiKey ? [apiKey] : [])\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.defaultBaseURL) 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 = this.searchOrder(proposed)\n proposed.searchProvider = this.activeSearchId(proposed)\n if (proposed.searchEnabled && !proposed.searchProvider) {\n fail('WEB_CREDENTIAL_MISSING', '需选择已安装的供应商并填写有效凭据。')\n }\n if (proposed.searchEnabled && this.entries.get(providerKey('fetch', 'http'))) {\n proposed.fetchEnabled = true\n proposed.fetchProvider = 'http'\n }\n if (!proposed.searchEnabled) proposed.fetchEnabled = false\n if (proposed.fetchEnabled) {\n const entry = this.entries.get(providerKey('fetch', proposed.fetchProvider))\n if (!entry) proposed.fetchEnabled = false\n else if (!entry.configured) 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 entry of this.entries.values()) entry.unregister()\n this.entries.clear()\n this.listeners.clear()\n await this.pending\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_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 const table = domain.table('settings')\n const manager = 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.effect(() => async () => { await manager.dispose(); await domain.close() }, 'web-search-manager.dispose')\n ctx.provide('webSearchManager', manager)\n ctx.effect(() => registerBuiltins(manager), '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}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["MAX_RESPONSE_BYTES","MAX_RESPONSE_BYTES","record","readJSON","readJSON","record","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(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/ /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'\nexport interface TavilyOptions { apiKey: string; baseURL?: string; fetch?: typeof fetch }\nconst MAX_RESPONSE_BYTES = 2_000_000\nfunction endpoint(base: string): 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(/\\/+$/, '')}/search`\n}\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\nasync 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 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 } finally { await reader.cancel().catch(() => {}); reader.releaseLock() }\n}\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 { endpoint(this.options.baseURL ?? 'https://api.tavily.com'); 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)(endpoint(this.options.baseURL ?? 'https://api.tavily.com'), {\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 if (typeof row?.url !== 'string') continue\n let url: URL\n try { url = new URL(row.url) } catch { continue }\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) continue\n sources.push({\n url: url.href,\n ...(typeof row.title === 'string' ? { title: row.title.slice(0, 1000) } : {}),\n ...(typeof row.content === 'string' ? { snippet: row.content.slice(0, 8000) } : {}),\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_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-updated', () => { 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-updated'(kind: 'search' | 'fetch', id: string): void\n }\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAS,UAAU,OAAmC;CACpD,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,MAAM,OAAO,IAAI,SAAS,QAAQ,YAAY,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC,YAAY;EACjF,IAAI,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,YAClE,KAAK,IAAI,KAAK,CAAC,KAAK,SAAS,GAAG,KAAK,SAAS,eAC9C,wDAAwD,KAAK,IAAI,GAAG,OAAO,KAAA;EAChF,OAAO,qBAAqB,IAAI;CAClC,QAAQ;EAAE;CAAiB;AAC7B;AAEA,SAAS,OAAO,OAAqD;CACnE,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IACtE,QAAmC,KAAA;AACzC;;AAGA,SAAS,cAAc,QAA4C;CACjE,IAAI,OAAO,aAAa,OAAO,OAAO,cAAc,OAAO,OAAO,KAAK,SAAS,QAAQ,OAAO,KAAA;CAC/F,MAAM,UAAU,OAAO,KAAK;CAC5B,IAAI,QAAQ,UAAU,CAAC,CAAC,WAAW,GAAG,GACpC,IAAI;EACF,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,CAAC;EAC3C,IAAI,CAAC,YAAa,SAAS,SAAS,KAAA,KAAa,SAAS,SAAS,KAAM,OAAO,KAAA;EAChF,MAAM,OAAO,OAAO,SAAS,IAAI,KAAK;EACtC,OAAO,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,KAAK,KAAK,CAAC,KAAK,UACpE,KAAK,UAAU,KAAA;CACrB,QAAQ;EAAE;CAAiB;CAE7B,MAAM,SAAS,gCAAgC,KAAK,OAAO;CAC3D,IAAI,CAAC,UAAU,cAAc,KAAK,QAAQ,MAAM,GAAG,OAAO,KAAK,CAAC,GAAG,OAAO,KAAA;CAC1E,OAAO,QAAQ,MAAM,OAAO,QAAQ,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,UAAU,KAAA;AAC3E;;AAGA,eAAe,gBACb,MAAwD,WAAmB,QAClD;CACzB,QAAQ,eAAe;CACvB,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,SAAS,SAAS,YAAY,IAAI,CAAC,QAAQ,WAAW,MAAM,CAAC,IAAI,WAAW;CAClF,MAAM,QAAQ,iBAAiB,WAAW,MAAM,GAAG,SAAS;CAC5D,IAAI,YAAY,CAAC;CACjB,MAAM,UAAU,IAAI,SAAgB,GAAG,WAAW;EAChD,MAAM,gBAAgB,OAAO,OAAO,MAAM;EAC1C,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,YAAY,OAAO,oBAAoB,SAAS,OAAO;CACzD,CAAC;CACD,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CACxB,QAAQ,QAAQ,CAAC,CAAC,WAAW;GAAE,OAAO,eAAe;GAAG,OAAO,KAAK,MAAM;EAAE,CAAC,GAC7E,OACF,CAAC;CACH,UAAU;EACR,aAAa,KAAK;EAClB,IAAI;CACN;AACF;;AAGA,IAAa,yBAAb,MAAgE;CAE9D,KAAc;CACd;CAEA,YAAY,SAAgC;EAC1C,IAAI,CAAC,OAAO,UAAU,QAAQ,eAAe,KAAK,QAAQ,kBAAkB,KACvE,QAAQ,kBAAkB,YAAe,MAAM,IAAI,MAAM,wBAAwB;EACtF,KAAK,UAAU;CACjB;CAEA,YAAqB;EAAE,OAAO,KAAK,QAAQ,OAAO,UAAU;CAAE;CAE9D,MAAM,MAAM,SAA0B,QAA+C;EACnF,QAAQ,eAAe;EACvB,MAAM,MAAM,UAAU,QAAQ,GAAG;EACjC,IAAI,OAAO,KAAK,QAAQ,OAAO,UAAU,GACvC,IAAI;GAEF,MAAM,SAAS,MAAM,iBACnB,aAAY,KAAK,QAAQ,OAAO,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,KAAK,QAAQ,iBAAiB,MAC1F;GACA,QAAQ,eAAe;GACvB,MAAM,UAAU,cAAc,MAAM;GACpC,IAAI,YAAY,KAAA,GAAW,OAAO;IAAE,GAAG;IAAQ,KAAK,QAAQ;IAAK,MAAM;KAAE,MAAM;KAAQ;IAAQ;GAAE;EACnG,QAAQ;GAEN,QAAQ,eAAe;EACzB;EAEF,QAAQ,eAAe;EAEvB,OAAO,KAAK,QAAQ,OAAO,MAAM,SAAS,MAAM;CAClD;AACF;;;;ACrGA,SAAgB,kBAAkB,MAAc,UAA6B,CAAC,GAAW;CACvF,IAAI,SAAS;CACb,KAAK,MAAM,UAAU,QAAQ,OAAO,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,GAC7E,KAAK,MAAM,yBAAS,IAAI,IAAI,CAAC,QAAQ,mBAAmB,MAAM,CAAC,CAAC,GAAG,SAAS,OAAO,MAAM,KAAK,CAAC,CAAC,KAAK,YAAY;CAEnH,SAAS,OACN,QAAQ,4BAA4B,eAAe,CAAC,CACpD,QAAQ,4CAA4C,eAAe,CAAC,CACpE,QAAQ,iGAAiG,cAAc,CAAC,CACxH,QAAQ,2JAA2J,cAAc;CACpL,OAAO,OAAO,MAAM,GAAG,GAAI;AAC7B;AAEA,IAAa,kBAAb,cAAqC,SAAS;CAC5C;CACA,YAAY,QAAgB;EAC1B,MAAM,OAAO,OAAO,UAAU,MAAM,KAAK,UAAU,OAAO,UAAU,MAAM,SAAS;EACnF,MAAM,OAAO,gBAAgB,KAAK,MAAM,YAAY,oBAAoB;EACxE,KAAK,SAAS;CAChB;AACF;;AAGA,SAAgB,cAAc,OAAgB,UAA6B,CAAC,GAAa;CACvF,MAAM,uBAAO,IAAI,IAAa;CAC9B,MAAM,eAAyB,CAAC;CAChC,IAAI;CACJ,IAAI,UAAU;CACd,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,WAAW,OAAO,YAAY,YAAY,CAAC,KAAK,IAAI,OAAO,GAAG,SAAS;EACtG,KAAK,IAAI,OAAO;EAChB,MAAM,OAAO;EACb,IAAI,CAAC,QAAQ,OAAO,KAAK,SAAS,YAAY,KAAK,MAAM,OAAO,KAAK;EACrE,MAAM,cAAc,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,KAAK,IAAI,KAAK,cAAc,KAAK;EAC9G,IAAI,OAAO,gBAAgB,YAAY,YAAY,KAAK,KAAK,CAAC,aAAa,SAAS,WAAW,GAAG,aAAa,KAAK,WAAW;EAC/H,UAAU,KAAK;CACjB;CACA,IAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG,aAAa,KAAK,KAAK;CACtE,OAAO,IAAI,SACT,kBAAkB,aAAa,KAAK,GAAG,KAAK,eAAe,OAAO,GAClE,kBAAkB,QAAQ,sBAAsB,OAAO,CACzD;AACF;ACvCA,MAAa,qBAAqB;AAClC,MAAMA,uBAAqB;AAC3B,MAAM,aAAa;AAEnB,SAAgB,gBAAgB,OAAe,OAAO,oBAA4B;CAChF,MAAM,MAAM,IAAI,IAAI,IAAI;CACxB,IAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,UAAU,MAAM,IAAI,MAAM,qBAAqB;CACpG,IAAI,aAAa,IAAI,KAAK,KAAK;CAC/B,OAAO,IAAI;AACb;AAEA,SAAS,eAAe,OAAuB;CAC7C,OAAO,MACJ,QAAQ,UAAU,GAAG,CAAC,CACtB,QAAQ,SAAS,GAAG,CAAC,CACrB,QAAQ,SAAS,GAAG,CAAC,CACrB,QAAQ,WAAW,IAAG,CAAC,CACvB,QAAQ,UAAU,GAAG,CAAC,CACtB,QAAQ,WAAW,GAAG;AAC3B;AAEA,SAAS,UAAU,OAAuB;CACxC,OAAO,MAAM,QAAQ,YAAY,GAAG,CAAC,CAAC,QAAQ,QAAQ,GAAG;AAC3D;AAEA,SAAgB,iBAAiB,MAAc,SAAqC;CAClF,IAAI,MAAM,eAAe,KAAK,KAAK,CAAC;CACpC,IAAI;CACJ,IAAI;EAAE,MAAM,IAAI,IAAI,KAAK,OAAO;CAAE,QAAQ;EAAE;CAAO;CACnD,IAAI,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,UAAU;CACjF,MAAM,OAAO,IAAI;CAEjB,KADc,SAAS,oBAAoB,KAAK,SAAS,iBAAiB,OAC5D,IAAI,aAAa,SAAS,IAAI,aAAa,OAAO;EAC9D,MAAM,SAAS,IAAI,aAAa,IAAI,MAAM,KAAK,IAAI,aAAa,IAAI,GAAG;EACvE,IAAI,QAAQ;GACV,IAAI;IAAE,MAAM,IAAI,IAAI,MAAM;GAAE,QAAQ;IAAE;GAAO;GAC7C,IAAI,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,UAAU;EACnF;CACF;CACA,MAAM,aAAa,IAAI,SAAS,QAAQ,UAAU,EAAE;CACpD,IAAI,eAAe,oBAAoB,WAAW,SAAS,iBAAiB,GAAG;CAC/E,OAAO,IAAI;AACb;AAEA,SAAgB,sBAAsB,MAAc,UAAU,oBAAuC;CACnG,MAAM,UAA6B,CAAC;CACpC,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,KAAK;CACX,IAAI;CACJ,OAAQ,QAAQ,GAAG,KAAK,IAAI,GAAI;EAC9B,MAAM,MAAM,iBAAiB,MAAM,MAAM,MAAM,MAAM,IAAI,OAAO;EAChE,IAAI,CAAC,OAAO,KAAK,IAAI,GAAG,GAAG;EAC3B,KAAK,IAAI,GAAG;EACZ,MAAM,QAAQ,eAAe,UAAU,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAI;EAC5E,QAAQ,KAAK,QAAQ;GAAE;GAAK;EAAM,IAAI,EAAE,IAAI,CAAC;CAC/C;CACA,OAAO;AACT;AAEA,eAAe,SAAS,UAAoB,QAAuC;CACjF,MAAM,SAAS,SAAS,MAAM,UAAU;CACxC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,kBAAkB;CAC/C,IAAI,OAAO;CACX,MAAM,SAAuB,CAAC;CAC9B,IAAI;EACF,OAAO,MAAM;GACX,QAAQ,eAAe;GACvB,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,QAAQ,MAAM;GACd,IAAI,OAAOA,sBAAoB,MAAM,IAAI,MAAM,oBAAoB;GACnE,OAAO,KAAK,KAAK;EACnB;CACF,UAAU;EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;EAAG,OAAO,YAAY;CAAE;CACxE,MAAM,QAAQ,IAAI,WAAW,IAAI;CACjC,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,QAAQ;EAAE,MAAM,IAAI,OAAO,MAAM;EAAG,UAAU,MAAM;CAAO;CAC/E,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK;AACvC;;AAGA,IAAa,uBAAb,MAA+D;CAEhC;CAD7B,KAAS;CACT,YAAY,UAAqD,CAAC,GAAG;EAAxC,KAAA,UAAA;CAAyC;CACtE,YAAqB;EAAE,OAAO;CAAK;CACnC,MAAM,OAAO,SAA2B,QAAgD;EACtF,IAAI,CAAC,QAAQ,OAAO,KAAK,KAAK,QAAQ,MAAM,SAAS,KAAM,MAAM,IAAI,SAAS,SAAS,qBAAqB;EAC5G,MAAM,QAAQ,QAAQ,cAAc;EACpC,IAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI,MAAM,IAAI,SAAS,iBAAiB,qBAAqB;EAClH,IAAI;GACF,QAAQ,eAAe;GACvB,MAAM,MAAM,gBAAgB,QAAQ,MAAM,KAAK,CAAC;GAChD,MAAM,WAAW,OAAO,KAAK,QAAQ,SAAS,MAAA,CAAO,KAAK;IACxD,QAAQ;IAAO,UAAU;IAAU;IACnC,SAAS;KAAE,QAAQ;KAAa,cAAc;IAAW;GAC3D,CAAC;GACD,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,IAAI,gBAAgB,SAAS,MAAM;GAC3C;GACA,MAAM,UAAU,sBAAsB,MAAM,SAAS,UAAU,MAAM,GAAG,SAAS,OAAA,mCAAyB;GAC1G,OAAO;IAAE,SAAS,QAAQ,MAAM,GAAG,KAAK;IAAG,WAAW,QAAQ,SAAS;GAAM;EAC/E,SAAS,OAAO;GACd,IAAI,QAAQ,SAAS,MAAM,IAAI,SAAS,UAAU,aAAa;GAC/D,MAAM,cAAc,KAAK;EAC3B;CACF;AACF;AC5GA,SAAgBE,SAAO,OAAqD;CAC1E,OAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAmC,KAAA;AAC1G;AAEA,eAAsBC,WAAS,UAAoB,QAAwC;CACzF,MAAM,SAAS,SAAS,MAAM,UAAU;CACxC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,kBAAkB;CAC/C,IAAI,OAAO;CACX,MAAM,SAAuB,CAAC;CAC9B,IAAI;EACF,OAAO,MAAM;GACX,QAAQ,eAAe;GACvB,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,QAAQ,MAAM;GACd,IAAI,OAAA,KAA2B,MAAM,IAAI,MAAM,oBAAoB;GACnE,OAAO,KAAK,KAAK;EACnB;CACF,UAAU;EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;EAAG,OAAO,YAAY;CAAE;CACxE,MAAM,QAAQ,IAAI,WAAW,IAAI;CACjC,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,QAAQ;EAAE,MAAM,IAAI,OAAO,MAAM;EAAG,UAAU,MAAM;CAAO;CAC/E,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC;AACnD;AAEA,SAAgB,cAAc,MAAc,OAAO,IAAY;CAC7D,MAAM,MAAM,IAAI,IAAI,IAAI;CACxB,IAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,YAAY,IAAI,UAAU,IAAI,MAAM,MAAM,IAAI,MAAM,kBAAkB;CAC3H,OAAO,GAAG,IAAI,KAAK,QAAQ,QAAQ,EAAE,IAAI;AAC3C;AAEA,SAAgB,WAAW,KAAc,QAAgB,UAAmB,YAAkD;CAC5H,MAAM,MAAMD,SAAO,GAAG;CACtB,IAAI,OAAO,MAAM,YAAY,UAAU;CACvC,IAAI;CACJ,IAAI;EAAE,MAAM,IAAI,IAAI,IAAI,OAAiB;CAAE,QAAQ;EAAE;CAAO;CAC5D,IAAI,CAAC,CAAC,UAAU,OAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,UAAU;CACjF,MAAM,QAAQ,YAAY,OAAO,IAAI,cAAc,WAAY,IAAI,SAAS,CAAY,MAAM,GAAG,GAAI,IAAI,KAAA;CACzG,MAAM,UAAU,cAAc,OAAO,IAAI,gBAAgB,WAAY,IAAI,WAAW,CAAY,MAAM,GAAG,GAAI,IAAI,KAAA;CACjH,OAAO;EAAE,KAAK,IAAI;EAAM,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAAI,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;CAAG;AACvF;;;AC3BA,SAAS,iBAAiB,MAAuE;CAC/F,OAAO,MAAmC;EAEX;EAD7B,KAAc,KAAK;EACnB,YAAY,SAA6C;GAA5B,KAAA,UAAA;EAA6B;EAC1D,YAAqB;GACnB,IAAI;IAAE,cAAc,KAAK,QAAQ,WAAW,KAAK,UAAU,KAAK,IAAI;IAAG,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,CAAC;GAAE,QAC5G;IAAE,OAAO;GAAM;EACvB;EACA,MAAM,OAAO,SAA2B,QAAgD;GACtF,IAAI,CAAC,KAAK,UAAU,GAAG,MAAM,IAAI,SAAS,GAAG,KAAK,GAAG,UAAU,wBAAwB;GACvF,IAAI,CAAC,QAAQ,OAAO,KAAK,KAAK,QAAQ,MAAM,SAAS,KAAM,MAAM,IAAI,SAAS,SAAS,qBAAqB;GAC5G,MAAM,QAAQ,QAAQ,cAAc;GACpC,IAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI,MAAM,IAAI,SAAS,iBAAiB,qBAAqB;GAClH,MAAM,QAAQ,QAAQ,MAAM,KAAK;GACjC,IAAI;IACF,QAAQ,eAAe;IACvB,MAAM,MAAM,IAAI,IAAI,cAAc,KAAK,QAAQ,WAAW,KAAK,UAAU,KAAK,IAAI,CAAC;IACnF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,QAAQ;KAAE;KAAO;IAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,aAAa,IAAI,KAAK,KAAK;IAChH,MAAM,WAAW,OAAO,KAAK,QAAQ,SAAS,MAAA,CAAO,KAAK;KACxD,QAAQ,KAAK;KAAQ,UAAU;KAAS;KACxC,SAAS;MAAE,QAAQ;MAAoB,GAAG,KAAK,QAAQ,KAAK,QAAQ,MAAM;KAAE;KAC5E,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,UAAU,KAAK,KAAK;MAAE;MAAO;KAAM,CAAC,CAAC,EAAE,IAAI,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,SAAS,IAAI;KAChB,MAAM,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;KAC5C,MAAM,IAAI,gBAAgB,SAAS,MAAM;IAC3C;IACA,MAAM,UAAU,KAAK,MAAM,MAAME,WAAS,UAAU,MAAM,CAAC;IAC3D,OAAO;KAAE,SAAS,QAAQ,MAAM,GAAG,KAAK;KAAG,WAAW,QAAQ,SAAS;IAAM;GAC/E,SAAS,OAAO;IACd,IAAI,QAAQ,SAAS,MAAM,IAAI,SAAS,UAAU,aAAa;IAC/D,MAAM,cAAc,OAAO,CAAC,KAAK,QAAQ,MAAM,CAAC;GAClD;EACF;CACF;AACF;AAEA,MAAa,sBAAsB,iBAAiB;CAClD,IAAI;CAAS,UAAU;CAAgC,MAAM;CAAsB,QAAQ;CAC3F,UAAS,YAAW,EAAE,wBAAwB,OAAO;CACrD,QAAQ,EAAE,OAAO,aAAa;EAAE,GAAG;EAAO,OAAO,OAAO,KAAK;CAAE;CAC/D,MAAM,SAAS;EACb,MAAM,UAAUC,SAAOA,SAAO,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE;EAC9C,OAAO,MAAM,QAAQ,OAAO,IAAI,QAAQ,SAAQ,QAAO,WAAW,KAAK,OAAO,SAAS,aAAa,KAAK,CAAC,CAAC,IAAI,CAAC;CAClH;AACF,CAAC;AAED,MAAa,sBAAsB,iBAAiB;CAClD,IAAI;CAAS,UAAU;CAA2B,MAAM;CAAkB,QAAQ;CAClF,UAAS,YAAW;EAAE,eAAe,UAAU;EAAU,gBAAgB;CAAmB;CAC5F,OAAO,EAAE,OAAO,aAAa;EAAE;EAAO;EAAO,WAAW;EAAW,SAAS;CAAM;CAClF,MAAM,SAAS;EACb,MAAM,QAAQA,SAAOA,SAAOA,SAAO,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAC1DA,SAAOA,SAAO,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE;EACxC,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAQ,QAAO,WAAW,KAAK,OAAO,QAAQ,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC;CACzG;AACF,CAAC;AAED,MAAa,uBAAuB,iBAAiB;CACnD,IAAI;CAAU,UAAU;CAA6B,MAAM;CAAW,QAAQ;CAC9E,UAAS,YAAW;EAAE,aAAa;EAAQ,gBAAgB;CAAmB;CAC9E,OAAO,EAAE,OAAO,aAAa;EAAE,GAAG;EAAO,KAAK;CAAM;CACpD,MAAM,SAAS;EACb,MAAM,UAAUA,SAAO,OAAO,CAAC,EAAE;EACjC,OAAO,MAAM,QAAQ,OAAO,IAAI,QAAQ,SAAQ,QAAO,WAAW,KAAK,QAAQ,SAAS,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC;CAC/G;AACF,CAAC;AAED,MAAa,0BAA0B,iBAAiB;CACtD,IAAI;CAAa,UAAU;CAA6B,MAAM;CAAc,QAAQ;CACpF,UAAS,YAAW;EAAE,eAAe,UAAU;EAAU,gBAAgB;CAAmB;CAC5F,OAAO,EAAE,OAAO,aAAa;EAAE;EAAO,OAAO;CAAM;CACnD,MAAM,SAAS;EACb,MAAM,OAAOA,SAAO,OAAO,CAAC,EAAE;EAC9B,OAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,SAAQ,QAAO,WAAW,KAAK,OAAO,SAAS,aAAa,KAAK,CAAC,CAAC,IAAI,CAAC;CAC5G;AACF,CAAC;;;AC1FD,MAAM,qBAAqB;AAC3B,SAAS,SAAS,MAAsB;CACtC,MAAM,MAAM,IAAI,IAAI,IAAI;CACxB,IAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,YAAY,IAAI,UAAU,IAAI,MAAM,MAAM,IAAI,MAAM,kBAAkB;CAC3H,OAAO,GAAG,IAAI,KAAK,QAAQ,QAAQ,EAAE,EAAE;AACzC;AACA,SAAS,OAAO,OAAqD;CACnE,OAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAmC,KAAA;AAC1G;AACA,eAAe,SAAS,UAAoB,QAAwC;CAClF,MAAM,SAAS,SAAS,MAAM,UAAU;CACxC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,kBAAkB;CAC/C,IAAI,OAAO;CACX,MAAM,SAAuB,CAAC;CAC9B,IAAI;EACF,OAAO,MAAM;GACX,QAAQ,eAAe;GACvB,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,QAAQ,MAAM;GACd,IAAI,OAAO,oBAAoB,MAAM,IAAI,MAAM,oBAAoB;GACnE,OAAO,KAAK,KAAK;EACnB;EACA,MAAM,QAAQ,IAAI,WAAW,IAAI;EACjC,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,QAAQ;GAAE,MAAM,IAAI,OAAO,MAAM;GAAG,UAAU,MAAM;EAAO;EAC/E,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC;CACnD,UAAU;EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;EAAG,OAAO,YAAY;CAAE;AAC1E;;AAEA,IAAa,uBAAb,MAA+D;CAEhC;CAD7B,KAAc;CACd,YAAY,SAAyC;EAAxB,KAAA,UAAA;CAAyB;CACtD,YAAqB;EACnB,IAAI;GAAE,SAAS,KAAK,QAAQ,WAAW,wBAAwB;GAAG,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,CAAC;EAAE,QACvG;GAAE,OAAO;EAAM;CACvB;CACA,MAAM,OAAO,SAA2B,QAAgD;EACtF,IAAI,CAAC,KAAK,UAAU,GAAG,MAAM,IAAI,SAAS,iBAAiB,wBAAwB;EACnF,IAAI,CAAC,QAAQ,OAAO,KAAK,KAAK,QAAQ,MAAM,SAAS,KAAM,MAAM,IAAI,SAAS,SAAS,qBAAqB;EAC5G,MAAM,QAAQ,QAAQ,cAAc;EACpC,IAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI,MAAM,IAAI,SAAS,iBAAiB,qBAAqB;EAClH,IAAI;GACF,QAAQ,eAAe;GACvB,MAAM,WAAW,OAAO,KAAK,QAAQ,SAAS,MAAA,CAAO,SAAS,KAAK,QAAQ,WAAW,wBAAwB,GAAG;IAC/G,QAAQ;IAAQ,UAAU;IAAS;IACnC,SAAS;KAAE,eAAe,UAAU,KAAK,QAAQ;KAAU,gBAAgB;KAAoB,QAAQ;IAAmB;IAC1H,MAAM,KAAK,UAAU;KACnB,OAAO,QAAQ,MAAM,KAAK;KAAG,aAAa;KAAO,cAAc;KAAS,OAAO;KAC/E,iBAAiB;KAAO,gBAAgB;KAAO,qBAAqB;KAAO,gBAAgB;IAC7F,CAAC;GACH,CAAC;GACD,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,IAAI,gBAAgB,SAAS,MAAM;GAC3C;GACA,MAAM,UAAU,OAAO,MAAM,SAAS,UAAU,MAAM,CAAC;GACvD,IAAI,CAAC,MAAM,QAAQ,SAAS,OAAO,GAAG,MAAM,IAAI,MAAM,wBAAwB;GAC9E,MAAM,UAA6B,CAAC;GACpC,KAAK,MAAM,OAAO,QAAQ,SAAS;IACjC,MAAM,MAAM,OAAO,GAAG;IACtB,IAAI,OAAO,KAAK,QAAQ,UAAU;IAClC,IAAI;IACJ,IAAI;KAAE,MAAM,IAAI,IAAI,IAAI,GAAG;IAAE,QAAQ;KAAE;IAAS;IAChD,IAAI,CAAC,CAAC,UAAU,OAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,UAAU;IACjF,QAAQ,KAAK;KACX,KAAK,IAAI;KACT,GAAI,OAAO,IAAI,UAAU,WAAW,EAAE,OAAO,IAAI,MAAM,MAAM,GAAG,GAAI,EAAE,IAAI,CAAC;KAC3E,GAAI,OAAO,IAAI,YAAY,WAAW,EAAE,SAAS,IAAI,QAAQ,MAAM,GAAG,GAAI,EAAE,IAAI,CAAC;KACjF,GAAI,OAAO,IAAI,mBAAmB,YAAY,OAAO,SAAS,KAAK,MAAM,IAAI,cAAc,CAAC,IACxF,EAAE,aAAa,IAAI,KAAK,IAAI,cAAc,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC;IACrE,CAAC;GACH;GACA,OAAO;IAAE,SAAS,QAAQ,MAAM,GAAG,KAAK;IAAG,WAAW,QAAQ,SAAS;GAAM;EAC/E,SAAS,OAAO;GACd,IAAI,QAAQ,SAAS,MAAM,IAAI,SAAS,iBAAiB,aAAa;GACtE,MAAM,cAAc,OAAO,CAAC,KAAK,QAAQ,MAAM,CAAC;EAClD;CACF;AACF;;;ACvEA,SAAS,SAAS,YAAsC;CACtD,IAAI,CAAC,yBAAyB,KAAK,WAAW,EAAE,KAAK,CAAC,WAAW,MAAM,KAAK,GAC1E,MAAM,IAAI,SAAS,eAAe,sBAAsB;CAE1D,IAAI,WAAW,iBAAiB,CAAC,0BAA0B,KAAK,WAAW,aAAa,GACtF,MAAM,IAAI,SAAS,cAAc,sBAAsB;CAEzD,IAAI,WAAW,gBAAgB,gBAAgB,WAAW,cAAc;CACxE,KAAK,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC,WAAW,WAAW,MAAM,GAAG,CAAC,WAAW,YAAY,QAAQ,CAAC,GAAY;EACzG,IAAI,CAAC,OAAO;EACZ,IAAI;GACF,MAAM,MAAM,IAAI,IAAI,KAAK;GACzB,IAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,UAAU,MAAM,IAAI,MAAM;EACjF,QAAQ;GAAE,MAAM,IAAI,SAAS,GAAG,MAAM,YAAY,sBAAsB;EAAE;CAC5E;AACF;AACA,eAAe,eAAkB,MAA0B,YACzD,eAAsC,QACtC,KAA2D;CAC3D,IAAI;CACJ,IAAI;EACF,QAAQ,eAAe;EACvB,SAAS,WAAW,gBAAgB,MAAM,cAAc,kBAAkB,WAAW,aAAa,IAAI,KAAA;EACtG,QAAQ,eAAe;EACvB,IAAI,WAAW,iBAAiB,CAAC,QAAQ,KAAK,GAAG,MAAM,IAAI,SAAS,sBAAsB,wBAAwB;EAClH,MAAM,WAAW,cAAc,SAAS;EACxC,OAAO,MAAM,IAAI;GAAE;GAAQ,SAAS,SAAS,UAAU,YAAY,MAAM,WAAW,EAAE,MAAM,WAAW;GACrG,WAAW,SAAS;GAAW,eAAe,SAAS;EAAc,CAAC;CAC1E,SAAS,OAAO;EAAE,MAAM,cAAc,OAAO,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;CAAE;AACvE;;AAEA,SAAgB,qBAAqB,KAAkB,eACrD,YAAgC,SAA4C;CAC5E,SAAS,UAAU;CACnB,OAAO,IAAI,uBAAuB;EAChC,IAAI,WAAW;EACf,kBAAkB,OAAO,OAAO;GAAE,GAAG;GAAY,oBAAoB;EAAkB,CAAC;EACxF,iBAAiB;EACjB,SAAS,SAAS,WAAW,eAAe,UAAU,YAAY,eAAe,SAAQ,YAAW;GAClG,MAAM,WAAW,QAAQ,OAAO;GAChC,IAAI,CAAC,SAAS,UAAU,GAAG,MAAM,IAAI,SAAS,aAAa,oBAAoB;GAC/E,OAAO,SAAS,OAAO,SAAS,MAAM;EACxC,CAAC;CACH,CAAyD;AAC3D;AACA,SAAgB,oBAAoB,KAAkB,eACpD,YAAgC,SAA2C;CAC3E,SAAS,UAAU;CACnB,OAAO,IAAI,sBAAsB;EAC/B,IAAI,WAAW;EACf,kBAAkB,OAAO,OAAO;GAAE,GAAG;GAAY,oBAAoB;EAAkB,CAAC;EACxF,iBAAiB;EACjB,QAAQ,SAAS,WAAW,eAAe,SAAS,YAAY,eAAe,SAAQ,YAAW;GAChG,MAAM,WAAW,QAAQ,OAAO;GAChC,IAAI,CAAC,SAAS,UAAU,GAAG,MAAM,IAAI,SAAS,aAAa,oBAAoB;GAC/E,OAAO,SAAS,MAAM,SAAS,MAAM;EACvC,CAAC;CACH,CAAwD;AAC1D;;;ACvDA,MAAM,QAAQ,OAAO,IAAI,gDAAgD;;;;;AAMzE,SAAS,UAAU,KAA2B;CAC5C,MAAM,UAAU;CAChB,IAAI,EAAE,QAAQ,2BAA2B,QAAQ,EAAE,QAAQ,0BAA0B,QAChF,CAAC,OAAO,OAAO,SAAS,kBAAkB,KAAK,CAAC,OAAO,OAAO,SAAS,iBAAiB,GAC3F,MAAM,IAAI,SAAS,sCAAsC,0BAA0B;CAErF,OAAO;AACT;AACA,SAAgB,eAAe,KAAkB,MAAoB,IAAqB;CACxF,OAAO,UAAU,GAAG,CAAC,CAAC,SAAS,WAAW,oBAAoB,iBAAiB,CAAC,IAAI,EAAE;AACxF;AAEA,SAAgB,mBAAmB,KAAkB,OAGtC;CACb,MAAM,UAAU,UAAU,GAAG;CAC7B,MAAM,OAAO,CAAC,QAAQ,iBAAiB,QAAQ,cAAc;CAC7D,IAAI,KAAK,MAAK,QAAO,OAAO,OAAO,KAAK,KAAK,CAAC,GAC5C,MAAM,IAAI,SAAS,yBAAyB,sBAAsB;CAEpE,MAAM,OAA0B,CAAC;CACjC,IAAI;EACF,KAAK,MAAM,CAAC,MAAM,QAAQ,CAAC,CAAC,UAAU,KAAK,EAAE,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,GAAY;GAC5E,OAAO,eAAe,KAAK,OAAO;IAAE,OAAO;IAAM,cAAc;GAAK,CAAC;GACrE,KAAK,WAAW;IAAE,OAAQ,IAA2C;GAAO,CAAC;GAC7E,MAAM,4BAAY,IAAI,IAAmE;GACzF,MAAM,MAAM,IAAI,KAAK,SAAS,IAAI,QAAQ,QAAQ,IAAI;GACtD,MAAM,QAAQ,IAAY,aAA6B;IACrD,MAAM,UAAU,MAAM,IAAI,MAAM,QAAQ;IACxC,UAAU,IAAI,IAAI;KAAE,UAAU;KAAU;IAAQ,CAAC;IACjD,OAAO;GACT;GACA,KAAK,WAAW;IAEd,KAAK,MAAM,CAAC,IAAI,QAAQ,WAAW,IAAI,IAAI,IAAI,EAAE,MAAM,IAAI,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ;GACpG,CAAC;GACD,KAAK,MAAM,CAAC,IAAI,aAAa,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,QAAQ,CAAC;GACtE,MAAM,eAAe;IACnB,IAAI,IAAY,UAA0B;KACxC,MAAM,UAAU,KAAK,IAAI,QAAQ;KACjC,IAAI,KAAK,KAAK,IAAI,OAAO;KACzB,OAAO;IACT;IACA,OAAO,IAAY;KACjB,MAAM,UAAU,OAAO,KAAK,KAAK,EAAE;KACnC,IAAI,SAAS;MAAE,UAAU,OAAO,EAAE;MAAG,MAAM,OAAO,MAAM,EAAE;KAAE;KAC5D,OAAO;IACT;IACA,QAAQ;KACN,MAAM,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC;KAC1B,MAAM,KAAK,GAAG;KACd,UAAU,MAAM;KAChB,KAAK,MAAM,MAAM,KAAK,MAAM,OAAO,MAAM,EAAE;IAC7C;GACF;GACA,KAAK,MAAM,OAAO;IAAC;IAAO;IAAU;GAAO,GAAY;IACrD,MAAM,SAAS,OAAO,yBAAyB,KAAK,GAAG;IACvD,OAAO,eAAe,KAAK,KAAK;KAAE,OAAO,aAAa;KAAM,cAAc;KAAM,UAAU;IAAK,CAAC;IAChG,KAAK,WAAW;KACd,IAAI,IAAI,SAAS,aAAa,MAAM;KACpC,IAAI,QAAQ,OAAO,eAAe,KAAK,KAAK,MAAM;UAC7C,OAAQ,IAA2C;IAC1D,CAAC;GACH;EACF;EACA,KAAK,MAAM,OAAO,CAAC,oBAAoB,iBAAiB,GAAY;GAClE,MAAM,SAAS,OAAO,yBAAyB,SAAS,GAAG;GAC3D,OAAO,eAAe,SAAS,KAAK;IAAE,GAAG;IAAQ,OAAO,KAAA;GAAU,CAAC;GACnE,KAAK,WAAW;IACd,IAAI,QAAQ,SAAS,KAAA,GAAW,OAAO,eAAe,SAAS,KAAK,MAAM;GAC5E,CAAC;EACH;CACF,SAAS,OAAO;EACd,KAAK,MAAM,WAAW,KAAK,QAAQ,GAAG,QAAQ;EAC9C,MAAM,IAAI,SAAS,2BAA2B,4BAA4B,EAAE,OAAO,MAAM,CAAC;CAC5F;CACA,IAAI,UAAU;CACd,aAAa;EACX,IAAI,SAAS;EACb,UAAU;EACV,KAAK,MAAM,WAAW,KAAK,QAAQ,GAAG,QAAQ;CAChD;AACF;;;ACrFA,SAAgB,iBAAiB,KAAkB,eAAkD;CACnG,MAAM,aAAgC,CAAC;CACvC,MAAM,kBAAkB,YAAgC,YAAmC;EACzF,IAAI,WAAW,YAAY,eAAe,KAAK,UAAU,WAAW,QAAQ,GAAG,aAAa,CAAC;EAC7F,IAAI,eAAe,KAAK,UAAU,WAAW,EAAE,GAAG,aAAa,CAAC;EAChE,MAAM,MAAM,qBAAqB,KAAK,eAAe,YAAY,OAAO;EACxE,WAAW,KAAK,GAAG;EACnB,OAAO;CACT;CACA,MAAM,iBAAiB,YAAgC,YAAkC;EACvF,IAAI,WAAW,YAAY,eAAe,KAAK,SAAS,WAAW,QAAQ,GAAG,aAAa,CAAC;EAC5F,IAAI,eAAe,KAAK,SAAS,WAAW,EAAE,GAAG,aAAa,CAAC;EAC/D,MAAM,MAAM,oBAAoB,KAAK,eAAe,YAAY,OAAO;EACvE,WAAW,KAAK,GAAG;EACnB,OAAO;CACT;CACA,IAAI;EACF,eAAe;GACb,IAAA;GAAsB,OAAO;GAAc,SAAS;GACpD,aAAa;EACf,SAAS,IAAI,qBAAqB,CAAC;EACnC,eAAe;GACb,IAAI;GAAoB,UAAU;GAAqB,OAAO;GAC9D,aAAa;GACb,gBAAgB;GAA2B,eAAe;GAC1D,kBAAkB;GAAM,gBAAgB;GAAe,SAAS;GAChE,WAAW;EACb,IAAG,YAAW,IAAI,8BAA8B;GAC9C,QAAQ,QAAQ;GAAQ,SAAS,QAAQ,WAAW;GACpD,OAAO;GAAwB,YAAY;GAC3C,WAAW;GAA6B,SAAS;EACnD,EAAE,CAAC;EACH,eAAe;GACb,IAAI;GAAO,OAAO;GAAO,aAAa;GACtC,gBAAgB;GAAsB,eAAe;GAA8B,SAAS;GAC5F,WAAW;EACb,IAAG,YAAW,IAAI,kBAAkB;GAClC,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ,WAAW;GAC1D,YAAY;GAAQ,qBAAqB;EAC3C,CAAC,CAAC;EACF,eAAe;GACb,IAAI;GAAS,OAAO;GAAS,aAAa;GAC1C,gBAAgB;GAAgC,eAAe;GAAgC,SAAS;GACxG,WAAW;EACb,IAAG,YAAW,IAAI,oBAAoB;GAAE,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ;EAAQ,CAAC,CAAC;EACjG,eAAe;GACb,IAAI;GAAS,OAAO;GAAM,aAAa;GACvC,gBAAgB;GAA2B,eAAe;GAAgC,SAAS;GACnG,WAAW;EACb,IAAG,YAAW,IAAI,oBAAoB;GAAE,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ;EAAQ,CAAC,CAAC;EACjG,eAAe;GACb,IAAI;GAAU,OAAO;GAAU,aAAa;GAC5C,gBAAgB;GAA6B,eAAe;GAAiC,SAAS;GACtG,WAAW;EACb,IAAG,YAAW,IAAI,qBAAqB;GAAE,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ;EAAQ,CAAC,CAAC;EAClG,eAAe;GACb,IAAI;GAAa,OAAO;GAAa,aAAa;GAClD,gBAAgB;GAA6B,eAAe;GAAoC,SAAS;GACzG,WAAW;EACb,IAAG,YAAW,IAAI,wBAAwB;GAAE,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ;EAAQ,CAAC,CAAC;EACrG,eAAe;GACb,IAAI;GAAU,OAAO;GAAU,gBAAgB;GAC/C,aAAa;GACb,eAAe;GAAiC,SAAS;GACzD,WAAW;EACb,IAAG,YAAW,IAAI,qBAAqB;GAAE,QAAQ,QAAQ,UAAU;GAAI,SAAS,QAAQ;EAAQ,CAAC,CAAC;EAClG,cAAc;GACZ,IAAI;GAAgB,UAAU;GAAQ,OAAO;GAAQ,SAAS;GAC9D,aAAa;EACf,IAAG,YAAW;GACZ,MAAM,SAAS;IACb,kBAAkB;IAAW,cAAc,QAAQ;IACnD,WAAW,QAAQ;IAAW,cAAc;IAAG,WAAW;GAC5D;GACA,MAAM,kBAAkB,KAAK,IAAI,MAAQ,KAAK,MAAM,QAAQ,YAAY,CAAC,CAAC;GAC1E,OAAO,IAAI,uBAAuB;IAEhC,QAAQ,IAAI,kBAAkB;KAAE,GAAG;KAAQ,cAAc,OAAO;KAAkB,WAAW;IAAgB,CAAC;IAC9G,QAAQ,IAAI,kBAAkB,MAAM;IACpC;GACF,CAAC;EACH,CAAC;CACH,SAAS,OAAO;EAAE,KAAK,MAAM,OAAO,WAAW,QAAQ,GAAG,IAAI;EAAG,MAAM;CAAM;CAC7E,aAAa;EAAE,KAAK,MAAM,OAAO,WAAW,OAAO,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI;CAAE;AACzE;;;;AChGA,SAAgBC,kBACd,KACA,SACA,MACY;CACZ,OAAOC,gBAAsB,KAAK,SAAS,MAAM,EAC/C,YAAW,WAAU,WAAW,MAAM,oCAAoC,KAAA,EAC5E,CAAC;AACH;;;ACOA,SAAS,KAAK,MAAc,SAAwB;CAAE,MAAM,IAAI,SAAS,SAAS,IAAI;AAAE;AACxF,SAAS,QAAQ,OAAe,KAAa,KAAa,OAAuB;CAC/E,IAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,OAAO,QAAQ,KAAK,KAAK,sBAAsB,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM;CACxH,OAAO;AACT;;AAEA,eAAe,UAAa,MAAwB,QAAiC;CACnF,OAAO,eAAe;CACtB,IAAI,YAAY,CAAC;CACjB,MAAM,UAAU,IAAI,SAAgB,GAAG,WAAW;EAChD,MAAM,gBAAgB,OAAO,IAAI,SAAS,eAAe,aAAa,CAAC;EACvE,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,YAAY,OAAO,oBAAoB,SAAS,OAAO;CACzD,CAAC;CACD,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,CAAC,WAAW;GAAE,OAAO,eAAe;GAAG,OAAO,KAAK;EAAE,CAAC,GAAG,OAAO,CAAC;CAC/G,UAAU;EAAE,IAAI;CAAE;AACpB;;AAGA,IAAa,mBAAb,MAA8B;CAaC;CAZ7B;CACA,0BAAkB,IAAI,IAAmB;CACzC,4BAAoB,IAAI,IAAgB;CACxC,UAAkB,QAAQ,QAAQ;CAClC,QAAgB;CAChB,YAAoB;CACpB,WAAmB;CACnB,gBAAwB;CACxB,kBAA0B;CAC1B;CACA,sCAA8B,IAAI,IAAgB;CAElD,YAAY,SAA0C;EAAzB,KAAA,UAAA;EAC3B,MAAM,UAAU,gBAAgB,QAAQ,WAAW,gBAAgB,CAAC;EACpE,KAAK,WAAW;GAAE,GAAG,gBAAgB;GAAG,GAAG;GAAS,aAAa,mBAAmB,OAAO;EAAE;EAC7F,KAAK,SAAS,mBAAmB,QAAQ,KAAK;GAC5C,MAAM,MAAM,aAAa,KAAK,SAAS,MAAM,QAAQ;GACrD,SAAS,MAAM,OAAO;IACpB,MAAM,MAAM,YAAY,MAAM,EAAE;IAChC,MAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG;IAClC,IAAI,OAAO;KAAE,KAAK,MAAM,KAAK;KAAG,KAAK,QAAQ,OAAO,GAAG;KAAG,KAAK,OAAO;IAAE;GAC1E;EACF,CAAC;CACH;CACA,UAAU,UAAkC;EAC1C,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa;GAAE,KAAK,UAAU,OAAO,QAAQ;EAAE;CACjD;CACA,SAAuB;EACrB,KAAK,MAAM,YAAY,KAAK,WAC1B,IAAI;GAAE,SAAS;EAAE,QAAQ,CAAoD;CAEjF;CACA,iBAAmC;EACjC,OAAO,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,CAAC,CAAC,QAAO,UAAS,MAAM,SAAS,QAAQ,CAAC,CAAC,KAAI,UAAS,MAAM,WAAW,EAAE;CAC7G;CACA,MAAc,IAAqB;EACjC,OAAO,QAAQ,KAAK,QAAQ,IAAI,YAAY,UAAU,EAAE,CAAC,CAAC,EAAE,WAAW,aAAa;CACtF;CACA,WAAmB,IAAqB;EACtC,MAAM,QAAQ,KAAK,QAAQ,IAAI,YAAY,UAAU,EAAE,CAAC;EACxD,OAAO,QAAQ,SAAS,KAAK,MAAM,KAAK,CAAC;CAC3C;CACA,MAAc,OAAuB;EACnC,IAAI;GAAE,OAAO,MAAM,cAAc,MAAM,SAAS,UAAU;EAAE,QACtD;GAAE,OAAO;EAAM;CACvB;CACA,YAAoB,WAAwB,KAAK,UAAoB;EACnE,OAAO,mBAAmB,KAAK,eAAe,GAAG,WAAU,OAAM,KAAK,MAAM,EAAE,CAAC;CACjF;CACA,eAAuB,WAAwB,KAAK,UAAkB;EACpE,OAAO,iBAAiB,KAAK,YAAY,QAAQ,IAAG,OAAM,KAAK,WAAW,EAAE,CAAC;CAC/E;CACA,SAAiB,OAAuB;EACtC,IAAI,KAAK,YAAY,KAAK,aAAa,CAAC,KAAK,MAAM,KAAK,GAAG,OAAO;EAClE,IAAI,KAAK,QAAQ,IAAI,YAAY,MAAM,MAAM,MAAM,WAAW,EAAE,CAAC,MAAM,OAAO,OAAO;EACrF,IAAI,MAAM,SAAS,SACjB,OAAO,KAAK,SAAS,gBAChB,KAAK,SAAS,kBAAkB,MAAM,WAAW,MACjD,KAAK,QAAQ,IAAI,YAAY,SAAS,MAAM,WAAW,EAAE,CAAC,MAAM;EAEvE,OAAO,KAAK,SAAS,iBAAiB,KAAK,eAAe,MAAM,MAAM,WAAW;CACnF;CACA,SAAoB;EAClB,MAAM,UAAU,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC;EACzC,OAAO;GACL,UAAU,gBAAgB,KAAK,QAAQ;GAAG,eAAe,KAAK;GAC9D,cAAc,QAAQ,MAAK,UAAS,MAAM,SAAS,YAAY,KAAK,SAAS,KAAK,CAAC;GACnF,aAAa,QAAQ,MAAK,UAAS,MAAM,SAAS,WAAW,KAAK,SAAS,KAAK,CAAC;GACjF,WAAW,QAAQ,KAAI,WAAU;IAC/B,GAAG,MAAM;IAAY,MAAM,MAAM;IAAM,YAAY,KAAK,MAAM,KAAK;IACnE,oBAAoB,MAAM,WAAW,uBAAuB;IAC5D,SAAS,MAAM,WAAW,uBAAA,oCACtB,KAAK,SAAS,UAAU,YAAY,MAAM,MAAM,MAAM,WAAW,EAAE,MAAM,MAAM,WAAW,iBAAiB,KAAA;IAC/G,OAAO,MAAM;IAAO,UAAU,MAAM;GACtC,EAAE,CAAC,CAAC,MAAM,GAAG,MAAM,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,cAAc,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;EACvF;CACF;CACA,MAAM,UAA8B;EAClC,MAAM,QAAQ,KAAK;EACnB,MAAM,WAAW,EAAE,KAAK;EACxB,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,QAAQ,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,WAAW;GACxE,IAAI,aAAa;GACjB,IAAI,MAAM,WAAW,uBAAA,qCAA4C,MAAM,WAAW,eAChF,IAAI;IAAE,aAAa,SAAS,MAAM,KAAK,QAAQ,kBAAkB,MAAM,WAAW,aAAa,EAAA,EAAI,KAAK,CAAC;GAAE,QACrG;IAAE,aAAa;GAAM;GAE7B,IAAI,KAAK,YAAY,UAAU,KAAK,SAAS,aAAa,KAAK,mBAAmB,KAAK,QAAQ,IAAI,GAAG,MAAM,OAAO;GACnH,IAAI,MAAM,eAAe,YAAY;IACnC,MAAM,aAAa;IACnB,IAAI,CAAC,YAAY,KAAK,MAAM,KAAK;GACnC;GACA,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG,KAAK,MAAM,KAAK;EAC1C,CAAC,CAAC;EACF,KAAK,OAAO;EACZ,OAAO,KAAK,OAAO;CACrB;CACA,MAAc,OAAqB;EACjC,KAAK,MAAM,UAAU,QAAQ,CAAC,KAAK,IAAI,KAAK,QAAQ,OAAO,GACzD,KAAK,MAAM,cAAc,OAAO,QAAQ,WAAW,MAAM;CAE7D;CACA,SAAiB,MAAoB,UAA0C;EAC7E,MAAM,MAAM,YAAY,MAAM,SAAS,EAAE;EACzC,MAAM,MAAM,KAAK,QAAQ,IAAI,GAAG;EAChC,IAAI,KAAK,KAAK,MAAM,GAAG;EACvB,MAAM,WAAY,SAAiF;EAEnG,MAAM,aAAmF;GACvF,IAAI,SAAS;GAAI,OAAO,OAAO,UAAU,UAAU,YAAY,SAAS,QAAQ,SAAS,QAAQ,SAAS;GAC1G,aAAa,OAAO,UAAU,gBAAgB,WAAW,SAAS,cAAc;GAChF,SAAS;IAAC;IAAQ;IAAW;GAAiB,CAAC,CAAC,SAAS,UAAU,WAAW,EAAE,IAAI,SAAU,UAAW;GACzG,oBAAoB,OAAO,UAAU,uBAAuB,YAAY,SAAS,qBAAqB,SAAS,qBAAqB,KAAA;GACpI,kBAAkB,qBAAqB,UAAU,gBAAgB;EACnE;EACA,KAAK,MAAM,SAAS;GAAC;GAAkB;GAAW;EAAgB,GAChE,IAAI,OAAO,WAAW,WAAW,UAAU,WAAW,SAAS,SAAS;EAE1E,IAAI,OAAO,UAAU,kBAAkB,YAAY,0BAA0B,KAAK,SAAS,aAAa,GAAG,WAAW,gBAAgB,SAAS;EAC/I,IAAI,UAAU,qBAAqB,MAAM,WAAW,mBAAmB;EACvE,KAAK,MAAM,SAAS,CAAC,aAAa,YAAY,GAC5C,IAAI;GACF,MAAM,MAAM,IAAI,IAAI,WAAW,UAAU,EAAE;GAC3C,IAAI,IAAI,aAAa,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI,UAAU,WAAW,SAAS,SAAU;EACjG,QAAQ,CAAkE;EAE5E,MAAM,QAAe;GAAE,YAAY,OAAO,OAAO,UAAU;GAAG;GAAM;GAClE,YAAY,WAAW,uBAAA,qCAA4C,CAAC,WAAW;GAC/E,OAAO;GAAG,UAAU;GAAG,wBAAQ,IAAI,IAAI;EAAE;EAC3C,KAAK,QAAQ,IAAI,KAAK,KAAK;EAG3B,MAAM,SAAS,UAAU;EACzB,MAAM,iBAAiB,SAAS,YAAY,SAAS,OAAO,qBAAqB,sBAC7E,SAAS,WAAW,SAAS,OAAO,iBAAiB,SAAS,KAAA;EAClE,IAAI,WAAW,uBAAA,qCAA4C,WAAW,kBAAkB,UACnF,CAAC,KAAK,QAAQ,IAAI,YAAY,MAAM,MAAM,CAAC,GAAG;GACjD,IAAI,SAAS,UAAU;IACrB,KAAK,SAAS,cAAc,KAAK,SAAS,YAAY,KAAI,OAAM,OAAO,SAAS,SAAS,KAAK,EAAE;IAChG,IAAI,KAAK,SAAS,mBAAmB,QAAQ,KAAK,SAAS,iBAAiB,SAAS;GACvF,OAAO,IAAI,KAAK,SAAS,kBAAkB,QAAQ,KAAK,SAAS,gBAAgB,SAAS;GAC1F,MAAM,YAAY,YAAY,MAAM,MAAM;GAC1C,IAAI,KAAK,SAAS,UAAU,cAAc,CAAC,KAAK,SAAS,UAAU,MAAM,KAAK,SAAS,UAAU,OAAO,KAAK,SAAS,UAAU;EAClI;EACA,KAAU,QAAQ;EAClB,IAAI,SAAS,UAAU;GACrB,MAAM,SAAS;GACf,OAAO;IAAE,IAAI,SAAS;IAAI,iBAAiB,KAAK,SAAS,KAAK;IAAG,SAAS,SAAS,WAAW;KAC5F,IAAI,OAAO,QAAQ,UAAU,YAAY,CAAC,QAAQ,MAAM,KAAK,KAAK,QAAQ,MAAM,SAAS,KAAM,KAAK,uBAAuB,mBAAmB;KAC9I,MAAM,QAAQ,KAAK,IAAI,QAAQ,QAAQ,cAAc,KAAK,SAAS,YAAY,GAAG,KAAK,KAAK,GAAG,KAAK,SAAS,UAAU;KACvH,OAAO,KAAK,QAAQ,OAAO,QAAQ,OAAO,UAAU,aAAa;MAC/D,MAAM,SAAS,MAAM,OAAO,OAAO;OAAE,GAAG;OAAS,OAAO,QAAQ,MAAM,KAAK;OAAG,YAAY;MAAM,GAAG,QAAQ;MAC3G,MAAM,UAAU,OAAO,QAAQ,MAAM,GAAG,KAAK,CAAC,CAAC,QAAO,WAAU;OAC9D,IAAI;QAAE,MAAM,MAAM,IAAI,IAAI,OAAO,GAAG;QAAG,OAAO,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI;OAAS,QAAQ;QAAE,OAAO;OAAM;MACpJ,CAAC,CAAC,CAAC,KAAI,YAAW;OAAE,GAAG;OAAQ,OAAO,OAAO,OAAO,MAAM,GAAG,GAAI;OAAG,SAAS,OAAO,SAAS,MAAM,GAAG,GAAI;MAAE,EAAE;MAC9G,OAAO;OAAE,GAAG;OAAQ,SAAS,OAAO,SAAS,MAAM,GAAG,GAAM;OAAG;OAC7D,WAAW,OAAO,aAAa,OAAO,QAAQ,SAAS;MAAM;KACjE,CAAC;IACH;GAAE;EACJ;EACA,MAAM,QAAQ;EACd,OAAO;GAAE,IAAI,SAAS;GAAI,iBAAiB,KAAK,SAAS,KAAK;GAAG,QAAQ,SAAS,WAChF,KAAK,QAAQ,OAAO,QAAQ,OAAO,SAAS,aAAa;IACvD,MAAM,SAAS,MAAM,MAAM,MAAM,SAAS,QAAQ;IAClD,MAAM,UAAU,OAAO,KAAK,QAAQ,MAAM,GAAG,QAAQ,aAAa;IAClE,OAAO;KAAE,GAAG;KAAQ,MAAM;MAAE,GAAG,OAAO;MAAM;KAAQ;KAAG,WAAW,OAAO,aAAa,QAAQ,WAAW,OAAO,KAAK,QAAQ;IAAO;GACtI,CAAC;EAAE;CACP;;CAEA,uBAAuB,YAAgC,SAA4C;EACjG,OAAO,KAAK,yBAAyB,qBAAqB,KAAK,QAAQ,KAAK,KAAK,sBAAsB,GAAG,YAAY,OAAO,CAAC;CAChI;;CAEA,sBAAsB,YAAgC,SAA2C;EAC/F,OAAO,KAAK,yBAAyB,oBAAoB,KAAK,QAAQ,KAAK,KAAK,sBAAsB,GAAG,YAAY,OAAO,CAAC;CAC/H;CACA,wBAAuD;EACrD,OAAO;GAAE,gBAAgB,gBAAgB,KAAK,QAAQ;GAAG,oBAAmB,QAAO,KAAK,QAAQ,kBAAkB,GAAG;EAAE;CACzH;CACA,mBAA2B,UAAwC;EACjE,IAAI,KAAK,UAAU,KAAK,gBAAgB,YAAY;EACpD,MAAM,aAAa,SAAS;EAC5B,MAAM,YAAY;GAAE,KAAK,oBAAoB,OAAO,GAAG;GAAG,WAAW;EAAE;EACvE,KAAK,oBAAoB,IAAI,GAAG;EAChC,OAAO;CACT;CACA,MAAc,QAAW,OAAc,QACrC,KAAgF;EAChF,IAAI,CAAC,KAAK,SAAS,KAAK,GAAG,KAAK,gBAAgB,sBAAsB;EACtE,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,UAAU,iBAAiB,WAAW,MAAM,GAAG,KAAK,SAAS,SAAS;EAC5E,MAAM,WAAW,SAAS,YAAY,IAAI,CAAC,QAAQ,WAAW,MAAM,CAAC,IAAI,WAAW;EACpF,MAAM,QAAQ,KAAK;EACnB,MAAM,OAAO,IAAI,UAAU;EAC3B,IAAI,UAAU;EACd,IAAI;GACF,IAAI,UAAU,KAAK,SAAS,CAAC,KAAK,SAAS,KAAK,GAAG,KAAK,gBAAgB,oBAAoB;GAC5F,MAAM,UAAU;IACd,SAAS,KAAK,SAAS,UAAU,YAAY,MAAM,MAAM,MAAM,WAAW,EAAE,MAAM,MAAM,WAAW;IACnG,WAAW,KAAK,SAAS;IAAW,eAAe,KAAK,SAAS;GACnE;GACA,UAAU;GACV,MAAM,SAAS;GACf,MAAM,SAAS,MAAM,gBAAgB,IAAI,SAAS,QAAQ,GAAG,QAAQ;GACrE,IAAI,UAAU,KAAK,SAAS,CAAC,KAAK,SAAS,KAAK,GAAG,KAAK,eAAe,UAAU;GACjF,OAAO;EACT,SAAS,OAAO;GACd,IAAI,SAAS,MAAM,YAAY;GAC/B,IAAI,iBAAiB,YAAY,MAAM,SAAS,0BAA0B;IACxE,MAAM,aAAa;IAAO,KAAK,MAAM,KAAK;IAAG,KAAK,OAAO;GAC3D;GACA,IAAI,SAAS,WAAW,EAAE,iBAAiB,YAAY,MAAM,SAAS,2BACpE,MAAM,IAAI,SAAS,eAAe,aAAa;GAGjD,MAAM,OAAO,cAAc,KAAK;GAChC,MAAM,IAAI,SAAS,IAAI,MAAM,KAAK,GAAG,MAAM,WAAW,GAAG,IAAI,KAAK,WAAW,KAAK,IAAI;EACxF,UAAU;GACR,aAAa,OAAO;GACpB,MAAM,OAAO,OAAO,UAAU;EAChC;CACF;CACA,OAAO,MAAqC,kBAA8C;EACxF,MAAM,OAAO,KAAK,QAAQ,KAAK,YAAY;GACzC,IAAI,KAAK,UAAU,KAAK,gBAAgB,YAAY;GACpD,IAAI,qBAAqB,KAAK,SAAS,UAAU,KAAK,uBAAuB,oBAAoB;GACjG,MAAM,WAAwB;IAAE,GAAG,gBAAgB,IAAI;IAAG,UAAU,mBAAmB;GAAE;GACzF,QAAQ,SAAS,YAAY,GAAG,IAAI,MAAM;GAC1C,QAAQ,SAAS,YAAY,GAAG,GAAG,MAAM;GACzC,QAAQ,SAAS,WAAW,KAAM,MAAS,OAAO;GAClD,QAAQ,SAAS,eAAe,KAAM,KAAS,MAAM;GACrD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,SAAS,GAAG;IAC7D,MAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG;IAClC,IAAI,UAAU,MAAM,WAAW,uBAAA,qCAA4C,CAAC,MAAM,WAAW,mBACxF,UAAU,KAAK,SAAS,UAAU,MAAM,KAAK,sBAAsB,cAAc;IACtF,IAAI;KAAE,SAAS,UAAU,OAAO,gBAAgB,KAAK;IAAE,QACjD;KAAE,KAAK,sBAAsB,6BAA6B;IAAE;GACpE;GACA,MAAM,KAAK,QAAQ;GACnB,SAAS,cAAc,CAAC,GAAG,IAAI,IAAI,SAAS,WAAW,CAAC;GACxD,SAAS,iBAAiB,KAAK,eAAe,QAAQ;GACtD,MAAM,mBAAmB,CAAC,KAAK,SAAS,iBACnC,KAAK,UAAU,SAAS,WAAW,MAAM,KAAK,UAAU,KAAK,SAAS,WAAW;GACtF,IAAI,SAAS,iBAAiB,CAAC,SAAS,kBAAkB,kBACxD,KAAK,0BAA0B,oBAAoB;GAErD,IAAI,SAAS,cAAc;IACzB,MAAM,QAAQ,KAAK,QAAQ,IAAI,YAAY,SAAS,SAAS,aAAa,CAAC;IAE3E,KADwB,CAAC,KAAK,SAAS,gBAAgB,SAAS,kBAAkB,KAAK,SAAS,mBACxE,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,0BAA0B,oBAAoB;GAC5G;GACA,KAAK,YAAY;GACjB,KAAK,SAAS;GACd,KAAK,MAAM;GACX,KAAK,OAAO;GACZ,IAAI;IAAE,MAAM,KAAK,QAAQ,KAAK,QAAQ;GAAE,QAClC;IACJ,KAAK,gBAAgB;IACrB,KAAK,OAAO;IACZ,KAAK,0BAA0B,yBAAyB;GAC1D;GACA,KAAK,WAAW;GAChB,KAAK,gBAAgB;GACrB,KAAK,YAAY;GACjB,KAAK,OAAO;GACZ,OAAO,KAAK,OAAO;EACrB,CAAC;EACD,KAAK,UAAU,KAAK,WAAW,CAAC,SAAS,CAAC,CAAC;EAC3C,OAAO;CACT;CACA,MAAM,UAAyB;EAC7B,KAAK,WAAW;EAChB,KAAK,SAAS;EACd,KAAK,MAAM;EACX,KAAK,OAAO;EACZ,KAAK,MAAM,OAAO,CAAC,GAAG,KAAK,mBAAmB,GAAG,IAAI;EACrD,MAAM,KAAK;EACX,KAAK,OAAO;EACZ,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;CACvB;AACF;;;AChUA,MAAa,iBAAiB,EAAE,OAAO;CACrC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CACvC,eAAe,EAAE,QAAQ;CAAG,cAAc,EAAE,QAAQ;CACpD,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE;CAAG,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE;CACpE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;CACtD,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CAAG,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;CACtF,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAI,CAAC,CAAC,IAAI,IAAO;CAAG,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAI,CAAC,CAAC,IAAI,GAAO;CACzG,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,uCAAuC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CACjG,QAAO,UAAS,OAAO,KAAK,KAAK,CAAC,CAAC,UAAU,EAAE;AACpD,CAAC,CAAC,CAAC,OAAO;AACV,MAAa,eAAe,EAAE,OAAO;CACnC,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CAAG,UAAU,eAAe,KAAK,EAAE,UAAU,KAAK,CAAC;AACpG,CAAC,CAAC,CAAC,OAAO;AACV,MAAa,uBAAuB,eAAe,OAAO,EACxD,aAAa,eAAe,MAAM,YAAY,SAAS,EACzD,CAAC,CAAC,CAAC,WAAU,cAAa;CAAE,GAAG;CAAU,aAAa,mBAAmB,QAAQ;AAAE,EAAE;AACrF,MAAa,oBAAoB,aAAa;CAC5C,MAAM;CAAyB,SAAS;CACxC,QAAQ,EAAE,UAAU,YAA2D,oBAAoB,EAAE;AACvG,CAAC;;;ACZD,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAO;CAAe;CAAiB;CAAc;AAAW;AAMvF,eAAsB,MAAM,KAA6B;CACvD,MAAM,OAAO;CACb,MAAM,SAAS,MAAM,IAAI,cAAc,KAAK,iBAAiB;CAE7D,IAAI;CACJ,IAAI,aAAa,YAAY;EAAE,MAAM,SAAS,QAAQ;EAAG,MAAM,OAAO,MAAM;CAAE,GAAG,4BAA4B;CAC7G,MAAM,QAAQ,OAAO,MAAM,UAAU;CACrC,MAAM,UAAU,UAAU,IAAI,iBAAiB;EAC7C,KAAK,IAAI;EAAK,SAAS,MAAM,IAAI,QAAQ;EACzC,mBAAmB,OAAM,SAAQ,MAAM,KAAK,YAAY,QAAQ,cAAc,GAAG,CAAC,EAAA,EAAI;EACtF,OAAM,aAAY,MAAM,IAAI,UAAU,QAAQ;CAChD,CAAC;CACD,IAAI,QAAQ,oBAAoB,OAAO;CACvC,IAAI,GAAG,uCAAuC;EAAE,QAAa,QAAQ;CAAE,CAAC;CACxE,IAAI,GAAG,2CAA2C;EAAE,QAAa,QAAQ;CAAE,CAAC;CAC5E,IAAI,aAAa,iBAAiB,IAAI,KAAK;EACzC,gBAAgB,QAAQ,OAAO,CAAC,CAAC;EACjC,mBAAmB,OAAM,SAAQ,MAAM,KAAK,YAAY,QAAQ,cAAc,GAAG,CAAC,EAAA,EAAI;CACxF,CAAC,GAAG,8BAA8B;CAClC,IAAI,aAAaC,kBAAgB,MAAM,wBAAwB,OAAO,UAAU,SAAS,WAA+B;EACtH,IAAI;GACF,OAAO,eAAe;GACtB,IAAI,aAAa,UAAU,OAAO;IAAE,IAAI;IAAM,OAAO,MAAM,QAAQ,QAAQ;GAAE;GAC7E,IAAI,aAAa,UAAU;IACzB,MAAM,SAAS,aAAa,UAAU,OAAO;IAC7C,IAAI,CAAC,OAAO,SAAS,OAAO;KAAE,IAAI;KAAO,OAAO;MAAE,MAAM;MAAsB,SAAS;MAAe,SAAS,CAAC;KAAE;IAAE;IACpH,OAAO;KAAE,IAAI;KAAM,OAAO,MAAM,QAAQ,OAAO,OAAO,KAAK,UAAU,OAAO,KAAK,gBAAgB;IAAE;GACrG;GACA,IAAI,aAAa,QAGf,OAAO;IAAE,IAAI;IAAM,OAAO,EAAE,UAAS,MADhB,IAAI,IAAI,OAAO;KAAE,OAAO;KAAwB,YAAY;IAAE,GAAG,MAAM,EAAA,CAChD,QAAQ,OAAO;GAAE;GAE/D,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAuB,SAAS;KAAS,SAAS,CAAC;IAAE;GAAE;EAC5F,SAAS,OAAO;GACd,OAAO;IAAE,IAAI;IAAO,OAAO;KACzB,MAAM,iBAAiB,WAAW,MAAM,OAAO;KAC/C,SAAS,iBAAiB,WAAW,MAAM,UAAU;KAAoB,SAAS,CAAC;IACrF;GAAE;EACJ;CACF,CAAC,GAAG,wBAAwB;AAC9B"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klarkxy/dsh-web-search-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Web Search: manage web search providers and public-page fetching from one settings page.",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
|
-
"node": ">=22"
|
|
9
|
+
"node": ">=22",
|
|
10
|
+
"dsh": ">=0.2.0-rc.2"
|
|
10
11
|
},
|
|
11
12
|
"main": "./lib/index.js",
|
|
12
13
|
"types": "./lib/index.d.ts",
|
|
@@ -78,18 +79,18 @@
|
|
|
78
79
|
"test": "vitest run --root ../.. --config vitest.editor-plugins.config.ts --maxWorkers=2 plugins/dsh-web-search-manager/src"
|
|
79
80
|
},
|
|
80
81
|
"dependencies": {
|
|
81
|
-
"@deepseek-ai/dsh-web-search-exa": ">=0.
|
|
82
|
-
"
|
|
83
|
-
"
|
|
82
|
+
"@deepseek-ai/dsh-web-search-exa": ">=0.2.0-rc.2",
|
|
83
|
+
"@klarkxy/dsh-plugin-kit": "0.2.0",
|
|
84
|
+
"zod": "^4.1.5"
|
|
84
85
|
},
|
|
85
86
|
"peerDependencies": {
|
|
86
|
-
"@deepseek-ai/cordis": "
|
|
87
|
-
"@deepseek-ai/dsh-credentials": ">=0.
|
|
88
|
-
"@deepseek-ai/dsh-storage-domain": ">=0.
|
|
89
|
-
"@deepseek-ai/dsh-tool-web": ">=0.
|
|
90
|
-
"@deepseek-ai/dsh-web": ">=0.
|
|
91
|
-
"@deepseek-ai/dsh-web-fetch-http": ">=0.
|
|
92
|
-
"@deepseek-ai/dsh-web-search-deepseek": ">=0.
|
|
87
|
+
"@deepseek-ai/cordis": ">=4.0.4",
|
|
88
|
+
"@deepseek-ai/dsh-credentials": ">=0.2.0-rc.2",
|
|
89
|
+
"@deepseek-ai/dsh-storage-domain": ">=0.2.0-rc.2",
|
|
90
|
+
"@deepseek-ai/dsh-tool-web": ">=0.2.0-rc.2",
|
|
91
|
+
"@deepseek-ai/dsh-web": ">=0.2.0-rc.2",
|
|
92
|
+
"@deepseek-ai/dsh-web-fetch-http": ">=0.2.0-rc.2",
|
|
93
|
+
"@deepseek-ai/dsh-web-search-deepseek": ">=0.2.0-rc.2"
|
|
93
94
|
},
|
|
94
95
|
"peerDependenciesMeta": {
|
|
95
96
|
"@deepseek-ai/dsh-credentials": {
|
|
@@ -112,16 +113,16 @@
|
|
|
112
113
|
}
|
|
113
114
|
},
|
|
114
115
|
"devDependencies": {
|
|
115
|
-
"@deepseek-ai/cordis": "
|
|
116
|
-
"@deepseek-ai/dsh-
|
|
117
|
-
"@deepseek-ai/dsh-
|
|
118
|
-
"@deepseek-ai/dsh-
|
|
119
|
-
"@deepseek-ai/dsh-web": "0.
|
|
120
|
-
"@deepseek-ai/dsh-web
|
|
121
|
-
"@deepseek-ai/dsh-web-
|
|
122
|
-
"
|
|
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",
|
|
123
124
|
"@types/react": "18.3.31",
|
|
124
|
-
"
|
|
125
|
+
"react": "^18.2.0"
|
|
125
126
|
},
|
|
126
127
|
"keywords": [
|
|
127
128
|
"dsh",
|
|
@@ -148,6 +149,6 @@
|
|
|
148
149
|
"registry": "https://registry.npmjs.org/"
|
|
149
150
|
},
|
|
150
151
|
"dshRelease": {
|
|
151
|
-
"contentHash": "
|
|
152
|
+
"contentHash": "105a9812be940d871dc250e068c104e4d6aad89f50f69b3e1457f9b9fb7612a4"
|
|
152
153
|
}
|
|
153
154
|
}
|