dsh-web-fetch-enhanced 0.0.3 → 0.0.5
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.en.md +8 -1
- package/README.md +8 -1
- package/lib/index.js +79 -9
- package/lib/types/address-policy.d.ts +8 -0
- package/lib/types/client/AllowlistCard.d.ts +1 -1
- package/lib/types/index.d.ts +22 -1
- package/lib/types/provider.d.ts +3 -2
- package/lib/types/resolver.d.ts +21 -1
- package/package.json +22 -21
package/README.en.md
CHANGED
|
@@ -29,7 +29,14 @@ With an empty CIDR allowlist, the security boundary remains equivalent to the na
|
|
|
29
29
|
- **Redirect revalidation** — same-origin redirects are resolved, validated, and pinned again at every hop;
|
|
30
30
|
- **Anonymous bounded GET requests** — no cookies, Authorization header, or URL credentials;
|
|
31
31
|
- **Resource limits** — URL length, response bytes, decoded characters, redirects, and time are bounded;
|
|
32
|
-
- **IPv4 and IPv6 coverage** — including IPv4-mapped IPv6 and active DNS64 / NAT64 checks
|
|
32
|
+
- **IPv4 and IPv6 coverage** — including IPv4-mapped IPv6 and active DNS64 / NAT64 checks;
|
|
33
|
+
- **Outbound HTTP proxy alignment** — seamlessly respects DSH global proxy routes (`HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` / `NO_PROXY`), while refusing unvalidated private IP literals from bypassing address checks through the proxy;
|
|
34
|
+
- **Dynamic system prompt alignment** — automatically injects explicit authorization guidance into the system prompt when non-public allowlists are configured, eliminating LLM refusal hallucinations when fetching authorized private destinations.
|
|
35
|
+
|
|
36
|
+
## Compatibility & Support Policy
|
|
37
|
+
|
|
38
|
+
- **Minimum Supported DSH Version**: `0.1.5-rc.2`
|
|
39
|
+
- **Support Policy**: This plugin **only supports DeepSeek Harness RC (Release Candidate) releases and future stable releases**. Compatibility is not maintained for rapid-moving Alpha or development snapshot versions.
|
|
33
40
|
|
|
34
41
|
## Quick start
|
|
35
42
|
|
package/README.md
CHANGED
|
@@ -29,7 +29,14 @@ DeepSeek Harness 原生 HTTP provider 默认拒绝所有非公网地址,这是
|
|
|
29
29
|
- **重定向逐跳复核**:仅跟随同源重定向,并在每一跳重新解析、校验和固定地址;
|
|
30
30
|
- **受限匿名请求**:只发送无 Cookie、无 Authorization、无 URL 凭据的 GET 请求;
|
|
31
31
|
- **完整资源上限**:限制 URL、响应字节、解码字符、重定向次数和超时时间;
|
|
32
|
-
- **IPv4 / IPv6 防护**:覆盖 IPv4-mapped IPv6 与活动 DNS64 / NAT64
|
|
32
|
+
- **IPv4 / IPv6 防护**:覆盖 IPv4-mapped IPv6 与活动 DNS64 / NAT64 目标检查;
|
|
33
|
+
- **全局出站代理协同**:无缝对接 DSH 全局 HTTP 代理路由(`HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` / `NO_PROXY`),同时严格禁止非公网 IP 字面量越权走代理,杜绝内网 SSRF 风险;
|
|
34
|
+
- **动态系统提示词协同**:当管理员配置了非公网白名单时,自动向模型系统提示词注入显式授权声明,消除模型因默认安全准则而产生“无法访问内网”的拒答幻觉。
|
|
35
|
+
|
|
36
|
+
## 版本兼容性与支持策略
|
|
37
|
+
|
|
38
|
+
- **最低支持的 DSH 版本**:`0.1.5-rc.2`
|
|
39
|
+
- **版本支持策略**:本插件**仅对 DeepSeek Harness 的 RC(Release Candidate)候选发布版本及后续稳定正式版提供支持**。由于 Alpha 或开发快照版本更迭频繁且缺乏稳定的 API 保证,本插件不再对 Alpha 等非 RC 阶段版本进行维护与适配。
|
|
33
40
|
|
|
34
41
|
## 快速开始
|
|
35
42
|
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import ipaddr from "ipaddr.js";
|
|
|
4
4
|
import { WebError } from "@deepseek-ai/dsh-web";
|
|
5
5
|
import { deadline, timeoutOf } from "@deepseek-ai/dsh-timeout";
|
|
6
6
|
import { lookup } from "node:dns/promises";
|
|
7
|
+
import { proxyRouteFor } from "@deepseek-ai/dsh-http-proxy";
|
|
7
8
|
//#region lib/types/address-policy.js
|
|
8
9
|
/**
|
|
9
10
|
* Immutable address policy. Public unicast remains allowed. A non-public address
|
|
@@ -39,6 +40,22 @@ var AddressPolicy = class {
|
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
};
|
|
43
|
+
/** Return true only for globally reachable unicast, matching the native provider. */
|
|
44
|
+
function isPublicIpAddress(input) {
|
|
45
|
+
const parsed = parseAddress(input);
|
|
46
|
+
return parsed !== void 0 && isPublicAddress(parsed);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether a hostname is an IP literal that resolves to a non-public address.
|
|
50
|
+
*
|
|
51
|
+
* A proxied hop skips address resolution because the proxy resolves the origin,
|
|
52
|
+
* but an IP literal needs no resolution. Handing an unverified non-public literal
|
|
53
|
+
* to a proxy would risk reaching loopback or private services (SSRF).
|
|
54
|
+
*/
|
|
55
|
+
function isNonPublicIpLiteral(hostname) {
|
|
56
|
+
const unbracketed = stripIpv6Brackets(hostname);
|
|
57
|
+
return isIP(unbracketed) !== 0 && !isPublicIpAddress(unbracketed);
|
|
58
|
+
}
|
|
42
59
|
function isPublicAddress(address) {
|
|
43
60
|
return address.range() === "unicast";
|
|
44
61
|
}
|
|
@@ -206,6 +223,16 @@ function embeddedIpv4Address(bytes, prefixLength) {
|
|
|
206
223
|
const beforeReservedOctet = 8 - prefixBytes;
|
|
207
224
|
return [...bytes.slice(prefixBytes, prefixBytes + beforeReservedOctet), ...bytes.slice(9, 13 - beforeReservedOctet)].join(".");
|
|
208
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Default proxy route resolver: resolves proxy route via @deepseek-ai/dsh-http-proxy.
|
|
228
|
+
*/
|
|
229
|
+
function defaultProxyRoute(url) {
|
|
230
|
+
const route = proxyRouteFor(url);
|
|
231
|
+
return route.proxied ? {
|
|
232
|
+
proxied: true,
|
|
233
|
+
dispatcher: route.dispatcher
|
|
234
|
+
} : { proxied: false };
|
|
235
|
+
}
|
|
209
236
|
/** Fetch while preserving the URL hostname for Host and TLS SNI. */
|
|
210
237
|
async function requestPinned(url, addresses, headers, signal) {
|
|
211
238
|
const { Agent, fetch } = await import("undici");
|
|
@@ -231,6 +258,24 @@ async function requestPinned(url, addresses, headers, signal) {
|
|
|
231
258
|
throw error;
|
|
232
259
|
}
|
|
233
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Fetch through the dispatcher the proxy policy already installed, letting the proxy resolve the origin.
|
|
263
|
+
* No address set is pinned because the proxy performs the lookup. The dispatcher is process-wide,
|
|
264
|
+
* so connections are pooled and the caller does not close it.
|
|
265
|
+
*/
|
|
266
|
+
async function requestVia(dispatcher, url, headers, signal) {
|
|
267
|
+
const { fetch } = await import("undici");
|
|
268
|
+
return {
|
|
269
|
+
response: await fetch(url, {
|
|
270
|
+
method: "GET",
|
|
271
|
+
redirect: "manual",
|
|
272
|
+
headers,
|
|
273
|
+
signal,
|
|
274
|
+
dispatcher
|
|
275
|
+
}),
|
|
276
|
+
close: () => Promise.resolve()
|
|
277
|
+
};
|
|
278
|
+
}
|
|
234
279
|
/** Create a Node lookup callback that returns only the prevalidated answer set. */
|
|
235
280
|
function createPinnedLookup(addresses) {
|
|
236
281
|
return (hostname, options, callback) => {
|
|
@@ -374,10 +419,12 @@ var EnhancedHttpFetchProvider = class {
|
|
|
374
419
|
id;
|
|
375
420
|
limits;
|
|
376
421
|
resolveAddresses;
|
|
377
|
-
|
|
422
|
+
resolveProxy;
|
|
423
|
+
constructor(id, limits, resolveAddresses, resolveProxy = defaultProxyRoute) {
|
|
378
424
|
this.id = id;
|
|
379
425
|
this.limits = limits;
|
|
380
426
|
this.resolveAddresses = resolveAddresses;
|
|
427
|
+
this.resolveProxy = resolveProxy;
|
|
381
428
|
}
|
|
382
429
|
available() {
|
|
383
430
|
return true;
|
|
@@ -436,11 +483,14 @@ var EnhancedHttpFetchProvider = class {
|
|
|
436
483
|
}
|
|
437
484
|
}
|
|
438
485
|
async requestOnce(url, signal) {
|
|
486
|
+
const headers = {
|
|
487
|
+
"user-agent": this.limits.userAgent,
|
|
488
|
+
"accept": "text/html,application/xhtml+xml,text/*;q=0.9,application/json;q=0.8"
|
|
489
|
+
};
|
|
439
490
|
try {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}, signal);
|
|
491
|
+
const route = await this.resolveProxy(url);
|
|
492
|
+
if (route.proxied && route.dispatcher && !isNonPublicIpLiteral(url.hostname)) return await requestVia(route.dispatcher, url, headers, signal);
|
|
493
|
+
return await requestPinned(url, await this.resolveAddresses(url.hostname, signal), headers, signal);
|
|
444
494
|
} catch (error) {
|
|
445
495
|
if (error instanceof WebError) throw error;
|
|
446
496
|
throw translateAbortOrNetwork(error, signal);
|
|
@@ -573,8 +623,18 @@ const Config = z.object({
|
|
|
573
623
|
maxRedirects: z.number().default(5),
|
|
574
624
|
userAgent: z.string().default(DEFAULT_USER_AGENT)
|
|
575
625
|
});
|
|
626
|
+
/** Build prompt guidance copy informing the model of authorized non-public destinations. */
|
|
627
|
+
function formatAllowlistPrompt(config) {
|
|
628
|
+
const cidrs = config.allowCidrs ?? [];
|
|
629
|
+
const hostnames = config.allowHostnames ?? [];
|
|
630
|
+
if (cidrs.length === 0 && hostnames.length === 0) return "";
|
|
631
|
+
const items = [];
|
|
632
|
+
if (cidrs.length > 0) items.push(`CIDRs: ${cidrs.join(", ")}`);
|
|
633
|
+
if (hostnames.length > 0) items.push(`hostnames: ${hostnames.join(", ")}`);
|
|
634
|
+
return `The operator has explicitly authorized web_fetch access to the following non-public destinations: [${items.join("; ")}]. You can safely fetch these endpoints.`;
|
|
635
|
+
}
|
|
576
636
|
/** Construct the provider without mounting it, useful for tests and custom compositions. */
|
|
577
|
-
function createProvider(config = {}) {
|
|
637
|
+
function createProvider(config = {}, proxyResolver) {
|
|
578
638
|
const resolved = resolveConfig(config);
|
|
579
639
|
assertProviderId(resolved.providerId);
|
|
580
640
|
assertPositiveFinite("maxResponseBytes", resolved.maxResponseBytes);
|
|
@@ -592,7 +652,7 @@ function createProvider(config = {}) {
|
|
|
592
652
|
maxRedirects: resolved.maxRedirects,
|
|
593
653
|
userAgent: resolved.userAgent
|
|
594
654
|
};
|
|
595
|
-
return new EnhancedHttpFetchProvider(resolved.providerId, limits, createAllowlistResolver(policy));
|
|
655
|
+
return new EnhancedHttpFetchProvider(resolved.providerId, limits, createAllowlistResolver(policy), proxyResolver);
|
|
596
656
|
}
|
|
597
657
|
function isUnloading(ctx) {
|
|
598
658
|
const state = ctx.fiber?.state;
|
|
@@ -609,7 +669,9 @@ function apply(ctx, config) {
|
|
|
609
669
|
setSource: (source) => {
|
|
610
670
|
current = source;
|
|
611
671
|
},
|
|
612
|
-
onChange: () => {
|
|
672
|
+
onChange: () => {
|
|
673
|
+
ctx.emit("system-prompt/change");
|
|
674
|
+
},
|
|
613
675
|
validate: (value) => {
|
|
614
676
|
if (resolveConfig(value).providerId !== providerId) throw new Error("web-fetch-enhanced: providerId cannot be changed through live settings");
|
|
615
677
|
createProvider(value);
|
|
@@ -628,6 +690,14 @@ function apply(ctx, config) {
|
|
|
628
690
|
settingsCtx.effect(() => () => {
|
|
629
691
|
if (isUnloading(ctx)) return;
|
|
630
692
|
current = () => config;
|
|
693
|
+
ctx.emit("system-prompt/change");
|
|
694
|
+
});
|
|
695
|
+
});
|
|
696
|
+
ctx.inject(["systemPrompt"], (promptCtx) => {
|
|
697
|
+
promptCtx.systemPrompt.section({
|
|
698
|
+
name: "web-fetch-enhanced:allowlist",
|
|
699
|
+
order: 2105,
|
|
700
|
+
text: () => formatAllowlistPrompt(current())
|
|
631
701
|
});
|
|
632
702
|
});
|
|
633
703
|
const dynamicProvider = {
|
|
@@ -665,4 +735,4 @@ function assertNonNegativeInteger(field, value) {
|
|
|
665
735
|
if (!Number.isInteger(value) || value < 0) throw new Error(`web-fetch-enhanced: ${field} must be a non-negative integer`);
|
|
666
736
|
}
|
|
667
737
|
//#endregion
|
|
668
|
-
export { Config, DEFAULT_PROVIDER_ID, DEFAULT_USER_AGENT, SETTINGS_NAMESPACE, apply, createProvider, inject, name };
|
|
738
|
+
export { Config, DEFAULT_PROVIDER_ID, DEFAULT_USER_AGENT, SETTINGS_NAMESPACE, apply, createProvider, defaultProxyRoute, formatAllowlistPrompt, inject, isNonPublicIpLiteral, name };
|
|
@@ -19,6 +19,14 @@ export declare class AddressPolicy {
|
|
|
19
19
|
}
|
|
20
20
|
/** Return true only for globally reachable unicast, matching the native provider. */
|
|
21
21
|
export declare function isPublicIpAddress(input: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a hostname is an IP literal that resolves to a non-public address.
|
|
24
|
+
*
|
|
25
|
+
* A proxied hop skips address resolution because the proxy resolves the origin,
|
|
26
|
+
* but an IP literal needs no resolution. Handing an unverified non-public literal
|
|
27
|
+
* to a proxy would risk reaching loopback or private services (SSRF).
|
|
28
|
+
*/
|
|
29
|
+
export declare function isNonPublicIpLiteral(hostname: string): boolean;
|
|
22
30
|
/** WHATWG URL retains brackets around IPv6 hostnames; IP parsers do not. */
|
|
23
31
|
export declare function stripIpv6Brackets(hostname: string): string;
|
|
24
32
|
//# sourceMappingURL=address-policy.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SettingsScope } from '@deepseek-ai/dsh-client-
|
|
1
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
2
2
|
import type { LocaleKey } from './locales.ts';
|
|
3
3
|
export interface AllowlistSettings {
|
|
4
4
|
allowCidrs?: string[];
|
package/lib/types/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
8
8
|
import z from '@deepseek-ai/schemastery';
|
|
9
9
|
import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
10
10
|
import { EnhancedHttpFetchProvider } from './provider.ts';
|
|
11
|
+
import type { ProxyRouteResolver } from './resolver.ts';
|
|
11
12
|
/** Explicit product User-Agent used by default. */
|
|
12
13
|
export declare const DEFAULT_USER_AGENT = "dsh-web-fetch-enhanced/0.1.0";
|
|
13
14
|
/** Default provider id; select it in the dsh-web row with fetchProvider. */
|
|
@@ -38,8 +39,28 @@ export interface Config {
|
|
|
38
39
|
userAgent?: string;
|
|
39
40
|
}
|
|
40
41
|
export declare const Config: z<Config>;
|
|
42
|
+
interface SystemPromptSeam {
|
|
43
|
+
section(section: {
|
|
44
|
+
name: string;
|
|
45
|
+
order: number;
|
|
46
|
+
text: string | ((context?: unknown) => string);
|
|
47
|
+
}): () => void;
|
|
48
|
+
}
|
|
49
|
+
declare module '@deepseek-ai/cordis' {
|
|
50
|
+
interface Context {
|
|
51
|
+
systemPrompt?: SystemPromptSeam;
|
|
52
|
+
}
|
|
53
|
+
interface Events {
|
|
54
|
+
'system-prompt/change'(): void;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Build prompt guidance copy informing the model of authorized non-public destinations. */
|
|
58
|
+
export declare function formatAllowlistPrompt(config: Config): string;
|
|
41
59
|
/** Construct the provider without mounting it, useful for tests and custom compositions. */
|
|
42
|
-
export declare function createProvider(config?: Config): EnhancedHttpFetchProvider;
|
|
60
|
+
export declare function createProvider(config?: Config, proxyResolver?: ProxyRouteResolver): EnhancedHttpFetchProvider;
|
|
61
|
+
export { isNonPublicIpLiteral } from './address-policy.ts';
|
|
62
|
+
export type { ProxyRouteResolver, ProxyRouteResult } from './resolver.ts';
|
|
63
|
+
export { defaultProxyRoute } from './resolver.ts';
|
|
43
64
|
/** Register the enhanced fetch provider and its live Web Profile settings section. */
|
|
44
65
|
export declare function apply(ctx: Context, config: Config): void;
|
|
45
66
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/provider.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WebFetchProvider, WebFetchRequest, WebFetchResult } from '@deepseek-ai/dsh-web';
|
|
2
|
-
import type { FetchResolver } from './resolver.ts';
|
|
2
|
+
import type { FetchResolver, ProxyRouteResolver } from './resolver.ts';
|
|
3
3
|
/** Resolved transport and response limits. */
|
|
4
4
|
export interface HttpFetchLimits {
|
|
5
5
|
maxResponseBytes: number;
|
|
@@ -13,7 +13,8 @@ export declare class EnhancedHttpFetchProvider implements WebFetchProvider {
|
|
|
13
13
|
readonly id: string;
|
|
14
14
|
private readonly limits;
|
|
15
15
|
private readonly resolveAddresses;
|
|
16
|
-
|
|
16
|
+
private readonly resolveProxy;
|
|
17
|
+
constructor(id: string, limits: HttpFetchLimits, resolveAddresses: FetchResolver, resolveProxy?: ProxyRouteResolver);
|
|
17
18
|
available(): boolean;
|
|
18
19
|
fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult>;
|
|
19
20
|
private followAndRead;
|
package/lib/types/resolver.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LookupAddress, LookupOptions } from 'node:dns';
|
|
2
|
-
import type { Response } from 'undici';
|
|
2
|
+
import type { Dispatcher, Response } from 'undici';
|
|
3
3
|
import { AddressPolicy } from './address-policy.ts';
|
|
4
4
|
/** DNS resolver shape used by Node and by focused tests. */
|
|
5
5
|
export type AddressResolver = (hostname: string, options: {
|
|
@@ -22,8 +22,28 @@ export interface PinnedResponse {
|
|
|
22
22
|
export declare function createAllowlistResolver(policy: AddressPolicy, resolver?: AddressResolver): FetchResolver;
|
|
23
23
|
/** Resolve once and reject the complete answer set when any entry is disallowed. */
|
|
24
24
|
export declare function resolveAllowedAddresses(hostname: string, signal: AbortSignal, policy: AddressPolicy, resolver?: AddressResolver): Promise<ValidatedAddress[]>;
|
|
25
|
+
/** Result of resolving a URL through the outbound proxy policy. */
|
|
26
|
+
export type ProxyRouteResult = {
|
|
27
|
+
readonly proxied: true;
|
|
28
|
+
readonly dispatcher: Dispatcher;
|
|
29
|
+
} | {
|
|
30
|
+
readonly proxied: false;
|
|
31
|
+
readonly dispatcher?: undefined;
|
|
32
|
+
};
|
|
33
|
+
/** Function deciding whether a URL should be routed through an outbound proxy. */
|
|
34
|
+
export type ProxyRouteResolver = (url: URL) => Promise<ProxyRouteResult> | ProxyRouteResult;
|
|
35
|
+
/**
|
|
36
|
+
* Default proxy route resolver: resolves proxy route via @deepseek-ai/dsh-http-proxy.
|
|
37
|
+
*/
|
|
38
|
+
export declare function defaultProxyRoute(url: URL): ProxyRouteResult;
|
|
25
39
|
/** Fetch while preserving the URL hostname for Host and TLS SNI. */
|
|
26
40
|
export declare function requestPinned(url: URL, addresses: readonly ValidatedAddress[], headers: Record<string, string>, signal: AbortSignal): Promise<PinnedResponse>;
|
|
41
|
+
/**
|
|
42
|
+
* Fetch through the dispatcher the proxy policy already installed, letting the proxy resolve the origin.
|
|
43
|
+
* No address set is pinned because the proxy performs the lookup. The dispatcher is process-wide,
|
|
44
|
+
* so connections are pooled and the caller does not close it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function requestVia(dispatcher: Dispatcher, url: URL, headers: Record<string, string>, signal: AbortSignal): Promise<PinnedResponse>;
|
|
27
47
|
type LookupCallback = (error: NodeJS.ErrnoException | null, address: string | LookupAddress[], family?: number) => void;
|
|
28
48
|
/** Create a Node lookup callback that returns only the prevalidated answer set. */
|
|
29
49
|
export declare function createPinnedLookup(addresses: readonly ValidatedAddress[]): (hostname: string, options: LookupOptions, callback: LookupCallback) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-web-fetch-enhanced",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Configurable non-public address allowlists for DeepSeek Harness web_fetch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -65,19 +65,20 @@
|
|
|
65
65
|
"access": "public"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|
|
68
|
-
"node": "^22.19.0 || >=24.0.0"
|
|
68
|
+
"node": "^22.19.0 || >=24.0.0",
|
|
69
|
+
"dsh": ">=0.1.5-rc.2"
|
|
69
70
|
},
|
|
70
71
|
"peerDependencies": {
|
|
71
72
|
"@deepseek-ai/cordis": "^4.0.1 || ^4.0.2",
|
|
72
|
-
"@deepseek-ai/dsh-timeout": "^0.1.
|
|
73
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
74
|
-
"@deepseek-ai/dsh-client-
|
|
75
|
-
"@deepseek-ai/dsh-client-
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-
|
|
77
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
73
|
+
"@deepseek-ai/dsh-timeout": "^0.1.5-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
|
|
77
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-rc.2",
|
|
79
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
80
|
+
"@deepseek-ai/dsh-web": "^0.1.5-rc.2",
|
|
81
|
+
"@deepseek-ai/dsh-http-proxy": "^0.1.5-rc.2"
|
|
81
82
|
},
|
|
82
83
|
"dependencies": {
|
|
83
84
|
"@deepseek-ai/schemastery": "^3.18.1 || ^3.18.2",
|
|
@@ -85,16 +86,16 @@
|
|
|
85
86
|
"undici": "^8.10.0"
|
|
86
87
|
},
|
|
87
88
|
"devDependencies": {
|
|
88
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
89
|
-
"@deepseek-ai/dsh-timeout": "^0.1.
|
|
90
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
91
|
-
"@deepseek-ai/dsh-client-
|
|
92
|
-
"@deepseek-ai/dsh-client-
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-
|
|
94
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
95
|
-
"@deepseek-ai/dsh-client-ui-
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
89
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
90
|
+
"@deepseek-ai/dsh-timeout": "^0.1.5-rc.2",
|
|
91
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.2",
|
|
92
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
|
|
94
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-rc.2",
|
|
96
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
97
|
+
"@deepseek-ai/dsh-web": "^0.1.5-rc.2",
|
|
98
|
+
"@deepseek-ai/dsh-http-proxy": "^0.1.5-rc.2",
|
|
98
99
|
"@types/js-yaml": "^4.0.9",
|
|
99
100
|
"@types/node": "^22.19.13",
|
|
100
101
|
"@types/react": "~18.3.1",
|