@klarkxy/dsh-web-search-manager 0.1.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/LICENSE +41 -0
- package/README.md +73 -0
- package/cordis.patch.yml +13 -0
- package/lib/client.inner.cjs +676 -0
- package/lib/client.inner.cjs.map +1 -0
- package/lib/client.js +846 -0
- package/lib/contracts.d.ts +79 -0
- package/lib/contracts.js +41 -0
- package/lib/contracts.js.map +1 -0
- package/lib/index.d.ts +60 -0
- package/lib/index.js +1070 -0
- package/lib/index.js.map +1 -0
- package/lib/tools.d.ts +9 -0
- package/lib/tools.js +56 -0
- package/lib/tools.js.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { WebFetchProvider, WebSearchProvider } from "@deepseek-ai/dsh-web";
|
|
2
|
+
//#region src/contracts.d.ts
|
|
3
|
+
declare const WEB_SEARCH_RPC_CHANNEL = "/web-search-manager";
|
|
4
|
+
type RpcResult<T = unknown> = {
|
|
5
|
+
ok: true;
|
|
6
|
+
value: T;
|
|
7
|
+
} | {
|
|
8
|
+
ok: false;
|
|
9
|
+
error: {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
details: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type ProviderKind = 'search' | 'fetch';
|
|
16
|
+
/** Management metadata only. Execution and source vocabulary belong to ctx.web. */
|
|
17
|
+
interface ProviderDescriptor {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly label: string;
|
|
20
|
+
readonly description: string;
|
|
21
|
+
readonly defaultBaseURL?: string;
|
|
22
|
+
readonly credentialRef?: string;
|
|
23
|
+
/** True when the key is shared with another surface (e.g. the chat model Key). The page must not delete it. */
|
|
24
|
+
readonly credentialShared?: boolean;
|
|
25
|
+
readonly billing: 'request' | 'model-and-tools' | 'none';
|
|
26
|
+
/** Public HTTPS page where the user can create an API key. */
|
|
27
|
+
readonly signupUrl?: string;
|
|
28
|
+
}
|
|
29
|
+
interface ProviderOptions {
|
|
30
|
+
readonly apiKey?: string;
|
|
31
|
+
readonly baseURL?: string;
|
|
32
|
+
readonly timeoutMs: number;
|
|
33
|
+
readonly maxFetchChars: number;
|
|
34
|
+
}
|
|
35
|
+
type SearchProviderFactory = (options: ProviderOptions) => WebSearchProvider;
|
|
36
|
+
type FetchProviderFactory = (options: ProviderOptions) => WebFetchProvider;
|
|
37
|
+
/** Never store credential values here. Keys are resolved by reference per call. */
|
|
38
|
+
interface WebSettings {
|
|
39
|
+
revision: number;
|
|
40
|
+
searchEnabled: boolean;
|
|
41
|
+
fetchEnabled: boolean;
|
|
42
|
+
searchProvider: string;
|
|
43
|
+
fetchProvider: string;
|
|
44
|
+
searchOrder: string[];
|
|
45
|
+
maxResults: number;
|
|
46
|
+
maxQueries: number;
|
|
47
|
+
timeoutMs: number;
|
|
48
|
+
maxFetchChars: number;
|
|
49
|
+
endpoints: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
declare const DEFAULT_SEARCH_ORDER: readonly ["ddg"];
|
|
52
|
+
declare const defaultSettings: () => WebSettings;
|
|
53
|
+
/** Keyed backends first, keyless last — same idea as OpenClaw auto-detect. */
|
|
54
|
+
declare function defaultSearchOrder(ids: readonly string[], keyed: (id: string) => boolean): string[];
|
|
55
|
+
declare function migrateSearchOrder(settings: {
|
|
56
|
+
searchOrder?: string[];
|
|
57
|
+
searchProvider?: string;
|
|
58
|
+
}): string[];
|
|
59
|
+
declare function resolveSearchOrder(knownIds: readonly string[], settings: Pick<WebSettings, 'searchOrder' | 'searchProvider'>, _keyed: (id: string) => boolean): string[];
|
|
60
|
+
declare function pickActiveSearch(order: readonly string[], configured: (id: string) => boolean): string;
|
|
61
|
+
interface ProviderView extends ProviderDescriptor {
|
|
62
|
+
kind: ProviderKind;
|
|
63
|
+
configured: boolean;
|
|
64
|
+
baseURL?: string;
|
|
65
|
+
calls: number;
|
|
66
|
+
failures: number;
|
|
67
|
+
}
|
|
68
|
+
interface WebStatus {
|
|
69
|
+
settings: WebSettings;
|
|
70
|
+
providers: ProviderView[];
|
|
71
|
+
searchActive: boolean;
|
|
72
|
+
fetchActive: boolean;
|
|
73
|
+
storageFailed: boolean;
|
|
74
|
+
}
|
|
75
|
+
declare function providerKey(kind: ProviderKind, id: string): string;
|
|
76
|
+
declare function validateBaseURL(value: string): string;
|
|
77
|
+
//#endregion
|
|
78
|
+
export { DEFAULT_SEARCH_ORDER, FetchProviderFactory, ProviderDescriptor, ProviderKind, ProviderOptions, ProviderView, RpcResult, SearchProviderFactory, WEB_SEARCH_RPC_CHANNEL, WebSettings, WebStatus, defaultSearchOrder, defaultSettings, migrateSearchOrder, pickActiveSearch, providerKey, resolveSearchOrder, validateBaseURL };
|
|
79
|
+
//# sourceMappingURL=contracts.d.ts.map
|
package/lib/contracts.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/contracts.ts
|
|
2
|
+
const WEB_SEARCH_RPC_CHANNEL = "/web-search-manager";
|
|
3
|
+
const DEFAULT_SEARCH_ORDER = ["ddg"];
|
|
4
|
+
const defaultSettings = () => ({
|
|
5
|
+
revision: 0,
|
|
6
|
+
searchEnabled: true,
|
|
7
|
+
fetchEnabled: true,
|
|
8
|
+
searchProvider: "ddg",
|
|
9
|
+
fetchProvider: "http",
|
|
10
|
+
searchOrder: [...DEFAULT_SEARCH_ORDER],
|
|
11
|
+
maxResults: 5,
|
|
12
|
+
maxQueries: 1,
|
|
13
|
+
timeoutMs: 3e4,
|
|
14
|
+
maxFetchChars: 1e5,
|
|
15
|
+
endpoints: {}
|
|
16
|
+
});
|
|
17
|
+
/** Keyed backends first, keyless last — same idea as OpenClaw auto-detect. */
|
|
18
|
+
function defaultSearchOrder(ids, keyed) {
|
|
19
|
+
return [...ids.filter(keyed), ...ids.filter((id) => !keyed(id))];
|
|
20
|
+
}
|
|
21
|
+
function migrateSearchOrder(settings) {
|
|
22
|
+
return settings.searchOrder ?? (settings.searchProvider ? [settings.searchProvider] : [...DEFAULT_SEARCH_ORDER]);
|
|
23
|
+
}
|
|
24
|
+
function resolveSearchOrder(knownIds, settings, _keyed) {
|
|
25
|
+
return [...new Set(settings.searchOrder.filter((id) => knownIds.includes(id)))];
|
|
26
|
+
}
|
|
27
|
+
function pickActiveSearch(order, configured) {
|
|
28
|
+
return order.find(configured) ?? "";
|
|
29
|
+
}
|
|
30
|
+
function providerKey(kind, id) {
|
|
31
|
+
return `${kind}:${id}`;
|
|
32
|
+
}
|
|
33
|
+
function validateBaseURL(value) {
|
|
34
|
+
const url = new URL(value);
|
|
35
|
+
if (url.protocol !== "https:" || url.username || url.password || url.search || url.hash) throw new Error("供应商地址必须是 HTTPS,且不能包含用户名、密码、查询参数或片段。");
|
|
36
|
+
return url.href.replace(/\/+$/, "");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { DEFAULT_SEARCH_ORDER, WEB_SEARCH_RPC_CHANNEL, defaultSearchOrder, defaultSettings, migrateSearchOrder, pickActiveSearch, providerKey, resolveSearchOrder, validateBaseURL };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","names":[],"sources":["../src/contracts.ts"],"sourcesContent":["import type { WebFetchProvider, WebSearchProvider } from '@deepseek-ai/dsh-web'\n\nexport const WEB_SEARCH_RPC_CHANNEL = '/web-search-manager'\nexport type RpcResult<T = unknown> = { ok: true; value: T } | {\n ok: false; error: { code: string; message: string; details: Record<string, unknown> }\n}\nexport type ProviderKind = 'search' | 'fetch'\n/** Management metadata only. Execution and source vocabulary belong to ctx.web. */\nexport interface ProviderDescriptor {\n readonly id: string\n readonly label: string\n readonly description: string\n readonly defaultBaseURL?: string\n readonly credentialRef?: string\n /** True when the key is shared with another surface (e.g. the chat model Key). The page must not delete it. */\n readonly credentialShared?: boolean\n readonly billing: 'request' | 'model-and-tools' | 'none'\n /** Public HTTPS page where the user can create an API key. */\n readonly signupUrl?: string\n}\nexport interface ProviderOptions {\n readonly apiKey?: string\n readonly baseURL?: string\n readonly timeoutMs: number\n readonly maxFetchChars: number\n}\nexport type SearchProviderFactory = (options: ProviderOptions) => WebSearchProvider\nexport type FetchProviderFactory = (options: ProviderOptions) => WebFetchProvider\n/** Never store credential values here. Keys are resolved by reference per call. */\nexport interface WebSettings {\n revision: number\n searchEnabled: boolean\n fetchEnabled: boolean\n searchProvider: string\n fetchProvider: string\n searchOrder: string[]\n maxResults: number\n maxQueries: number\n timeoutMs: number\n maxFetchChars: number\n endpoints: Record<string, string>\n}\nexport const DEFAULT_SEARCH_ORDER = ['ddg'] as const\n\nexport const defaultSettings = (): WebSettings => ({\n revision: 0, searchEnabled: true, fetchEnabled: true,\n searchProvider: 'ddg', fetchProvider: 'http', searchOrder: [...DEFAULT_SEARCH_ORDER],\n maxResults: 5, maxQueries: 1,\n timeoutMs: 30_000, maxFetchChars: 100_000, endpoints: {},\n})\n\n/** Keyed backends first, keyless last — same idea as OpenClaw auto-detect. */\nexport function defaultSearchOrder(ids: readonly string[], keyed: (id: string) => boolean): string[] {\n return [...ids.filter(keyed), ...ids.filter(id => !keyed(id))]\n}\n\nexport function migrateSearchOrder(settings: { searchOrder?: string[]; searchProvider?: string }): string[] {\n return settings.searchOrder ?? (settings.searchProvider ? [settings.searchProvider] : [...DEFAULT_SEARCH_ORDER])\n}\n\nexport function resolveSearchOrder(\n knownIds: readonly string[],\n settings: Pick<WebSettings, 'searchOrder' | 'searchProvider'>,\n _keyed: (id: string) => boolean,\n): string[] {\n return [...new Set(settings.searchOrder.filter(id => knownIds.includes(id)))]\n}\n\nexport function pickActiveSearch(order: readonly string[], configured: (id: string) => boolean): string {\n return order.find(configured) ?? ''\n}\nexport interface ProviderView extends ProviderDescriptor {\n kind: ProviderKind\n configured: boolean\n baseURL?: string\n calls: number\n failures: number\n}\nexport interface WebStatus {\n settings: WebSettings\n providers: ProviderView[]\n searchActive: boolean\n fetchActive: boolean\n storageFailed: boolean\n}\nexport function providerKey(kind: ProviderKind, id: string): string { return `${kind}:${id}` }\nexport function validateBaseURL(value: string): string {\n const url = new URL(value)\n if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) {\n throw new Error('供应商地址必须是 HTTPS,且不能包含用户名、密码、查询参数或片段。')\n }\n return url.href.replace(/\\/+$/, '')\n}\n"],"mappings":";AAEA,MAAa,yBAAyB;AAwCtC,MAAa,uBAAuB,CAAC,KAAK;AAE1C,MAAa,yBAAsC;CACjD,UAAU;CAAG,eAAe;CAAM,cAAc;CAChD,gBAAgB;CAAO,eAAe;CAAQ,aAAa,CAAC,GAAG,oBAAoB;CACnF,YAAY;CAAG,YAAY;CAC3B,WAAW;CAAQ,eAAe;CAAS,WAAW,CAAC;AACzD;;AAGA,SAAgB,mBAAmB,KAAwB,OAA0C;CACnG,OAAO,CAAC,GAAG,IAAI,OAAO,KAAK,GAAG,GAAG,IAAI,QAAO,OAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/D;AAEA,SAAgB,mBAAmB,UAAyE;CAC1G,OAAO,SAAS,gBAAgB,SAAS,iBAAiB,CAAC,SAAS,cAAc,IAAI,CAAC,GAAG,oBAAoB;AAChH;AAEA,SAAgB,mBACd,UACA,UACA,QACU;CACV,OAAO,CAAC,GAAG,IAAI,IAAI,SAAS,YAAY,QAAO,OAAM,SAAS,SAAS,EAAE,CAAC,CAAC,CAAC;AAC9E;AAEA,SAAgB,iBAAiB,OAA0B,YAA6C;CACtG,OAAO,MAAM,KAAK,UAAU,KAAK;AACnC;AAeA,SAAgB,YAAY,MAAoB,IAAoB;CAAE,OAAO,GAAG,KAAK,GAAG;AAAK;AAC7F,SAAgB,gBAAgB,OAAuB;CACrD,MAAM,MAAM,IAAI,IAAI,KAAK;CACzB,IAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,YAAY,IAAI,UAAU,IAAI,MACjF,MAAM,IAAI,MAAM,qCAAqC;CAEvD,OAAO,IAAI,KAAK,QAAQ,QAAQ,EAAE;AACpC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { FetchProviderFactory, ProviderDescriptor, ProviderOptions, SearchProviderFactory, WebSettings, WebStatus } from "./contracts.js";
|
|
2
|
+
import { WebFetchProvider, WebSearchProvider } from "@deepseek-ai/dsh-web";
|
|
3
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
4
|
+
//#region src/manager.d.ts
|
|
5
|
+
interface WebRegistry {
|
|
6
|
+
registerSearchProvider(provider: WebSearchProvider): () => void;
|
|
7
|
+
registerFetchProvider(provider: WebFetchProvider): () => void;
|
|
8
|
+
}
|
|
9
|
+
interface ManagerOptions {
|
|
10
|
+
web: WebRegistry;
|
|
11
|
+
initial?: Omit<WebSettings, 'searchOrder'> & {
|
|
12
|
+
searchOrder?: string[];
|
|
13
|
+
};
|
|
14
|
+
resolveCredential(ref: string): Promise<string | undefined>;
|
|
15
|
+
save(settings: WebSettings): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/** Manages consent and provider lifecycle. Selection and execution stay in ctx.web. */
|
|
18
|
+
declare class WebSearchManager {
|
|
19
|
+
private readonly options;
|
|
20
|
+
private settings;
|
|
21
|
+
private entries;
|
|
22
|
+
private listeners;
|
|
23
|
+
private pending;
|
|
24
|
+
private epoch;
|
|
25
|
+
private suspended;
|
|
26
|
+
private disposed;
|
|
27
|
+
private storageFailed;
|
|
28
|
+
constructor(options: ManagerOptions);
|
|
29
|
+
subscribe(listener: () => void): () => void;
|
|
30
|
+
private notify;
|
|
31
|
+
private knownSearchIds;
|
|
32
|
+
private keyed;
|
|
33
|
+
private configured;
|
|
34
|
+
private searchOrder;
|
|
35
|
+
private activeSearchId;
|
|
36
|
+
private selected;
|
|
37
|
+
status(): WebStatus;
|
|
38
|
+
refresh(): Promise<WebStatus>;
|
|
39
|
+
private abort;
|
|
40
|
+
private add;
|
|
41
|
+
private registration;
|
|
42
|
+
registerSearchProvider(descriptor: ProviderDescriptor, factory: SearchProviderFactory): () => void;
|
|
43
|
+
registerFetchProvider(descriptor: ProviderDescriptor, factory: FetchProviderFactory): () => void;
|
|
44
|
+
private execute;
|
|
45
|
+
update(next: Omit<WebSettings, 'revision'>, expectedRevision: number): Promise<WebStatus>;
|
|
46
|
+
dispose(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/index.d.ts
|
|
50
|
+
declare const name = "@klarkxy/dsh-web-search-manager";
|
|
51
|
+
declare const inject: readonly ["web", "credentials", "storageDomain", "connection", "webServer"];
|
|
52
|
+
declare module '@deepseek-ai/cordis' {
|
|
53
|
+
interface Context {
|
|
54
|
+
webSearchManager: WebSearchManager;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
declare function apply(ctx: Context): Promise<void>;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { type FetchProviderFactory, type ProviderDescriptor, type ProviderOptions, type SearchProviderFactory, WebSearchManager, apply, inject, name };
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|