@deepseek-ai/dsh-plugin-detail 0.0.0-stage → 0.2.2-alpha.2

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.
@@ -0,0 +1,126 @@
1
+ import type { DetailFailureReason, NpmFileSource } from './types.ts';
2
+ /** A read that must not fall back: the source exists but refused, failed, or exceeded a limit. */
3
+ export declare class DetailFailure extends Error {
4
+ readonly reason: DetailFailureReason;
5
+ /**
6
+ * @param reason - the failure kind a reader reports.
7
+ * @param message - the diagnostic, naming the source.
8
+ * @param options - the underlying error.
9
+ */
10
+ constructor(reason: DetailFailureReason, message: string, options?: ErrorOptions);
11
+ }
12
+ /** One file found by name lookup. */
13
+ export interface FoundFile {
14
+ /** `/`-separated path relative to the source root. */
15
+ readonly path: string;
16
+ readonly bytes: Uint8Array;
17
+ }
18
+ /** Files below one root, read by `/`-separated relative paths that never start with `/` or contain `.` or `..` segments. */
19
+ export interface DetailFiles {
20
+ /** Identity of the files' content: two sources with the same key read the same bytes. */
21
+ readonly key: string;
22
+ /**
23
+ * Read one regular file.
24
+ * @param path - path relative to the root.
25
+ * @param maxBytes - largest accepted size.
26
+ * @param signal - cancellation of the read.
27
+ * @returns the file's bytes, or undefined when it does not exist.
28
+ * @throws {DetailFailure} when the source fails or the file exceeds `maxBytes`.
29
+ */
30
+ read(path: string, maxBytes: number, signal: AbortSignal): Promise<Uint8Array | undefined>;
31
+ /**
32
+ * Read the README of a directory: `README.md`, `README.markdown`, or `README` in any letter case.
33
+ * @param dir - directory relative to the root; `''` for the root.
34
+ * @param maxBytes - largest accepted size.
35
+ * @param signal - cancellation of the read.
36
+ * @returns the file, or undefined when the directory has none.
37
+ * @throws {DetailFailure} when the source fails or the file exceeds `maxBytes`.
38
+ */
39
+ readme(dir: string, maxBytes: number, signal: AbortSignal): Promise<FoundFile | undefined>;
40
+ }
41
+ /** README names tried in order where a source cannot list a directory. */
42
+ export declare const README_NAMES: readonly string[];
43
+ /**
44
+ * Join a directory and a file name into a root-relative path.
45
+ * @param dir - directory relative to the root, `''` for the root.
46
+ * @param name - path relative to `dir`.
47
+ * @returns the joined path.
48
+ */
49
+ export declare function joinPath(dir: string, name: string): string;
50
+ /**
51
+ * Pick the README entry of a directory listing by the order of {@link README_NAMES}, then by name.
52
+ * @param names - file names of the directory.
53
+ * @returns the README name, or undefined.
54
+ */
55
+ export declare function readmeName(names: readonly string[]): string | undefined;
56
+ /** Reads one file: its bytes, or undefined when it is absent. */
57
+ export type ReadFile = (path: string, maxBytes: number, signal: AbortSignal) => Promise<Uint8Array | undefined>;
58
+ /**
59
+ * Read the first README of `names` that exists, for sources that cannot list a directory.
60
+ * @param read - reads one file.
61
+ * @param dir - directory relative to the root; `''` for the root.
62
+ * @param maxBytes - largest accepted size.
63
+ * @param signal - cancellation of the reads.
64
+ * @param names - the names to try, in order.
65
+ * @returns the file, or undefined when none exists.
66
+ * @throws {DetailFailure} what `read` throws.
67
+ */
68
+ export declare function readmeByName(read: ReadFile, dir: string, maxBytes: number, signal: AbortSignal, names?: readonly string[]): Promise<FoundFile | undefined>;
69
+ /**
70
+ * Files of a local package directory. A path whose real location leaves the directory reads as absent.
71
+ * @param root - absolute package directory.
72
+ * @param revision - the installed version, so a reinstalled package reads as different files.
73
+ * @returns the files.
74
+ */
75
+ export declare function localFiles(root: string, revision: string): DetailFiles;
76
+ /** Request settings of a remote file source. */
77
+ export interface RemoteFileOptions {
78
+ readonly timeoutMs: number;
79
+ /** Cancellation that outlives one read, such as the owning service's disposal. */
80
+ readonly lifetime: AbortSignal;
81
+ }
82
+ /** One HTTP answer: the body of a 2xx response, or the status of any other. */
83
+ export type FetchedBody = {
84
+ readonly ok: true;
85
+ readonly bytes: Uint8Array;
86
+ } | {
87
+ readonly ok: false;
88
+ readonly status: number;
89
+ };
90
+ /**
91
+ * GET a URL, following redirects within its origin, and read the body up to `maxBytes`.
92
+ * @param url - the request URL.
93
+ * @param maxBytes - largest accepted body.
94
+ * @param signal - cancellation of the read.
95
+ * @param options - deadline and service lifetime.
96
+ * @returns the body, or the status of a non-2xx response, including a redirect to another origin.
97
+ * @throws {DetailFailure} `network` when no response arrives or the body fails, `too-large` over `maxBytes`.
98
+ */
99
+ export declare function fetchBody(url: string, maxBytes: number, signal: AbortSignal, options: RemoteFileOptions): Promise<FetchedBody>;
100
+ /** Every npm file CDN, in the default order. */
101
+ export declare const NPM_FILE_SOURCES: readonly ["jsdelivr", "unpkg", "npmmirror"];
102
+ /**
103
+ * Order the configured npm file CDNs by a caller's preference: the preferred ones that are configured, in the preferred
104
+ * order, then the other configured ones in configured order. A preferred CDN that is not configured is not asked.
105
+ * @param configured - the configured CDNs in order.
106
+ * @param preferred - CDNs to ask first, such as those a Client measured as fastest; names other than CDNs are ignored.
107
+ * @returns the CDNs to ask, first to last.
108
+ */
109
+ export declare function npmFileSourceOrder(configured: readonly NpmFileSource[], preferred?: readonly string[]): NpmFileSource[];
110
+ /**
111
+ * Percent-encode each segment of a `/`-separated path for a URL.
112
+ * @param path - the path.
113
+ * @returns the encoded path.
114
+ */
115
+ export declare function encodePath(path: string): string;
116
+ /**
117
+ * Files of one published npm package version, read from public file CDNs in order. A 404 from a CDN means the package
118
+ * does not contain the file; a network failure or another status asks the next CDN.
119
+ * @param name - package name.
120
+ * @param version - exact version.
121
+ * @param sources - the CDNs to ask, first to last; never empty.
122
+ * @param options - deadline and service lifetime.
123
+ * @returns the files.
124
+ */
125
+ export declare function npmFiles(name: string, version: string, sources: readonly NpmFileSource[], options: RemoteFileOptions): DetailFiles;
126
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Read-only file sources for plugin detail documents: a local package directory and published npm package versions on
3
+ * public file CDNs, with bounded HTTP reads. Sources keep no state between calls.
4
+ */
5
+ import { lstat, readdir, readFile, realpath } from 'node:fs/promises';
6
+ import { join, relative, sep } from 'node:path';
7
+ /** A read that must not fall back: the source exists but refused, failed, or exceeded a limit. */
8
+ export class DetailFailure extends Error {
9
+ reason;
10
+ /**
11
+ * @param reason - the failure kind a reader reports.
12
+ * @param message - the diagnostic, naming the source.
13
+ * @param options - the underlying error.
14
+ */
15
+ constructor(reason, message, options) {
16
+ super(message, options);
17
+ this.reason = reason;
18
+ this.name = 'DetailFailure';
19
+ }
20
+ }
21
+ /** README names tried in order where a source cannot list a directory. */
22
+ export const README_NAMES = ['README.md', 'readme.md', 'Readme.md', 'README.markdown', 'README'];
23
+ const README_PATTERN = /^readme(?:\.md|\.markdown)?$/iu;
24
+ /**
25
+ * Join a directory and a file name into a root-relative path.
26
+ * @param dir - directory relative to the root, `''` for the root.
27
+ * @param name - path relative to `dir`.
28
+ * @returns the joined path.
29
+ */
30
+ export function joinPath(dir, name) {
31
+ return dir === '' ? name : `${dir}/${name}`;
32
+ }
33
+ /**
34
+ * Pick the README entry of a directory listing by the order of {@link README_NAMES}, then by name.
35
+ * @param names - file names of the directory.
36
+ * @returns the README name, or undefined.
37
+ */
38
+ export function readmeName(names) {
39
+ const rank = (name) => {
40
+ const index = README_NAMES.indexOf(name);
41
+ return index === -1 ? README_NAMES.length : index;
42
+ };
43
+ return names.filter(name => README_PATTERN.test(name)).sort((a, b) => rank(a) - rank(b) || (a < b ? -1 : 1))[0];
44
+ }
45
+ /**
46
+ * Read the first README of `names` that exists, for sources that cannot list a directory.
47
+ * @param read - reads one file.
48
+ * @param dir - directory relative to the root; `''` for the root.
49
+ * @param maxBytes - largest accepted size.
50
+ * @param signal - cancellation of the reads.
51
+ * @param names - the names to try, in order.
52
+ * @returns the file, or undefined when none exists.
53
+ * @throws {DetailFailure} what `read` throws.
54
+ */
55
+ export async function readmeByName(read, dir, maxBytes, signal, names = README_NAMES) {
56
+ for (const name of names) {
57
+ const path = joinPath(dir, name);
58
+ const bytes = await read(path, maxBytes, signal);
59
+ if (bytes !== undefined)
60
+ return { path, bytes };
61
+ }
62
+ return undefined;
63
+ }
64
+ function tooLarge(label, maxBytes) {
65
+ return new DetailFailure('too-large', `${label} exceeds ${String(maxBytes)} bytes`);
66
+ }
67
+ /**
68
+ * Files of a local package directory. A path whose real location leaves the directory reads as absent.
69
+ * @param root - absolute package directory.
70
+ * @param revision - the installed version, so a reinstalled package reads as different files.
71
+ * @returns the files.
72
+ */
73
+ export function localFiles(root, revision) {
74
+ const files = {
75
+ key: `local:${root}@${revision}`,
76
+ async read(path, maxBytes) {
77
+ let file;
78
+ try {
79
+ const base = await realpath(root);
80
+ file = await realpath(join(base, ...path.split('/')));
81
+ const inside = relative(base, file);
82
+ if (inside === '' || inside === '..' || inside.startsWith(`..${sep}`))
83
+ return undefined;
84
+ const info = await lstat(file);
85
+ if (!info.isFile())
86
+ return undefined;
87
+ if (info.size > maxBytes)
88
+ throw tooLarge(path, maxBytes);
89
+ }
90
+ catch (error) {
91
+ if (error instanceof DetailFailure)
92
+ throw error;
93
+ // A missing file or directory, or one the process may not read, is a file the package does not provide.
94
+ return undefined;
95
+ }
96
+ const bytes = await readFile(file);
97
+ /* v8 ignore next -- the file grew between its size check and its read; no test controls that timing */
98
+ if (bytes.byteLength > maxBytes)
99
+ throw tooLarge(path, maxBytes);
100
+ return bytes;
101
+ },
102
+ async readme(dir, maxBytes, signal) {
103
+ let names;
104
+ try {
105
+ names = (await readdir(join(root, ...dir === '' ? [] : dir.split('/')), { withFileTypes: true }))
106
+ .filter(entry => entry.isFile() || entry.isSymbolicLink()).map(entry => entry.name);
107
+ }
108
+ catch (_missing) {
109
+ // An absent or unreadable directory has no README.
110
+ return undefined;
111
+ }
112
+ const name = readmeName(names);
113
+ if (name === undefined)
114
+ return undefined;
115
+ const path = joinPath(dir, name);
116
+ const bytes = await files.read(path, maxBytes, signal);
117
+ return bytes === undefined ? undefined : { path, bytes };
118
+ },
119
+ };
120
+ return files;
121
+ }
122
+ /** Redirects followed within one origin, such as a renamed repository's raw files; a redirect to another origin is not followed. */
123
+ const MAX_REDIRECTS = 3;
124
+ /**
125
+ * GET a URL, following redirects within its origin, and read the body up to `maxBytes`.
126
+ * @param url - the request URL.
127
+ * @param maxBytes - largest accepted body.
128
+ * @param signal - cancellation of the read.
129
+ * @param options - deadline and service lifetime.
130
+ * @returns the body, or the status of a non-2xx response, including a redirect to another origin.
131
+ * @throws {DetailFailure} `network` when no response arrives or the body fails, `too-large` over `maxBytes`.
132
+ */
133
+ export async function fetchBody(url, maxBytes, signal, options) {
134
+ const combined = AbortSignal.any([signal, options.lifetime, AbortSignal.timeout(options.timeoutMs)]);
135
+ let response;
136
+ let target = url;
137
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
138
+ try {
139
+ response = await fetch(target, { signal: combined, redirect: 'manual' });
140
+ }
141
+ catch (error) {
142
+ // A cancelled read says nothing about the source, so it keeps the caller's reason.
143
+ signal.throwIfAborted();
144
+ options.lifetime.throwIfAborted();
145
+ throw new DetailFailure('network', `Could not fetch ${target}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
146
+ }
147
+ const location = response.status >= 300 && response.status < 400 ? response.headers.get('location') : null;
148
+ if (location === null || !URL.canParse(location, target) || new URL(location, target).origin !== new URL(url).origin)
149
+ break;
150
+ await response.body?.cancel();
151
+ target = new URL(location, target).href;
152
+ }
153
+ // The loop runs at least once.
154
+ const answer = response;
155
+ if (!answer.ok) {
156
+ await answer.body?.cancel();
157
+ return { ok: false, status: answer.status };
158
+ }
159
+ if (Number(answer.headers.get('content-length') ?? 0) > maxBytes) {
160
+ await answer.body?.cancel();
161
+ throw tooLarge(url, maxBytes);
162
+ }
163
+ const chunks = [];
164
+ let size = 0;
165
+ try {
166
+ for await (const chunk of answer.body ?? []) {
167
+ size += chunk.byteLength;
168
+ if (size > maxBytes)
169
+ throw tooLarge(url, maxBytes);
170
+ chunks.push(chunk);
171
+ }
172
+ }
173
+ catch (error) {
174
+ if (error instanceof DetailFailure)
175
+ throw error;
176
+ throw new DetailFailure('network', `Could not read ${url}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
177
+ }
178
+ return { ok: true, bytes: Buffer.concat(chunks) };
179
+ }
180
+ /** Every npm file CDN, in the default order. */
181
+ export const NPM_FILE_SOURCES = ['jsdelivr', 'unpkg', 'npmmirror'];
182
+ /**
183
+ * Order the configured npm file CDNs by a caller's preference: the preferred ones that are configured, in the preferred
184
+ * order, then the other configured ones in configured order. A preferred CDN that is not configured is not asked.
185
+ * @param configured - the configured CDNs in order.
186
+ * @param preferred - CDNs to ask first, such as those a Client measured as fastest; names other than CDNs are ignored.
187
+ * @returns the CDNs to ask, first to last.
188
+ */
189
+ export function npmFileSourceOrder(configured, preferred = []) {
190
+ const first = configured.filter(source => preferred.includes(source)).sort((a, b) => preferred.indexOf(a) - preferred.indexOf(b));
191
+ return [...first, ...configured.filter(source => !first.includes(source))];
192
+ }
193
+ /**
194
+ * Percent-encode each segment of a `/`-separated path for a URL.
195
+ * @param path - the path.
196
+ * @returns the encoded path.
197
+ */
198
+ export function encodePath(path) {
199
+ return path.split('/').map(encodeURIComponent).join('/');
200
+ }
201
+ const NPM_FILE_URLS = {
202
+ jsdelivr: (name, version, path) => `https://cdn.jsdelivr.net/npm/${name}@${version}/${encodePath(path)}`,
203
+ unpkg: (name, version, path) => `https://unpkg.com/${name}@${version}/${encodePath(path)}`,
204
+ npmmirror: (name, version, path) => `https://registry.npmmirror.com/${name}/${version}/files/${encodePath(path)}`,
205
+ };
206
+ /**
207
+ * Files of one published npm package version, read from public file CDNs in order. A 404 from a CDN means the package
208
+ * does not contain the file; a network failure or another status asks the next CDN.
209
+ * @param name - package name.
210
+ * @param version - exact version.
211
+ * @param sources - the CDNs to ask, first to last; never empty.
212
+ * @param options - deadline and service lifetime.
213
+ * @returns the files.
214
+ */
215
+ export function npmFiles(name, version, sources, options) {
216
+ const files = {
217
+ key: `npm:${name}@${version}`,
218
+ async read(path, maxBytes, signal) {
219
+ const failures = [];
220
+ for (const source of sources) {
221
+ const url = NPM_FILE_URLS[source](name, version, path);
222
+ try {
223
+ const body = await fetchBody(url, maxBytes, signal, options);
224
+ if (body.ok)
225
+ return body.bytes;
226
+ if (body.status === 404)
227
+ return undefined;
228
+ failures.push(`${url}: HTTP ${String(body.status)}`);
229
+ }
230
+ catch (error) {
231
+ if (!(error instanceof DetailFailure) || error.reason !== 'network')
232
+ throw error;
233
+ failures.push(error.message);
234
+ }
235
+ }
236
+ throw new DetailFailure('network', failures.join('; '));
237
+ },
238
+ readme: (dir, maxBytes, signal) => readmeByName((path, max, readSignal) => files.read(path, max, readSignal), dir, maxBytes, signal),
239
+ };
240
+ return files;
241
+ }
242
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Plugin detail documents without state: language chains, the `meta.detail` or README selection of a package, image
3
+ * destinations beside a document, and read-only file sources for local packages and published npm versions.
4
+ * @module @deepseek-ai/dsh-plugin-detail
5
+ */
6
+ export { DetailFailure, encodePath, fetchBody, joinPath, localFiles, NPM_FILE_SOURCES, npmFileSourceOrder, npmFiles, README_NAMES, readmeByName, readmeName, type DetailFiles, type FetchedBody, type FoundFile, type ReadFile, type RemoteFileOptions, } from './files.ts';
7
+ export { detailImage, languageChain, markdownOf, readPackageDocument, type PackageDocument } from './document.ts';
8
+ export { detailImageResponse, type DetailImage } from './response.ts';
9
+ export type { DetailFailureReason, NpmFileSource } from './types.ts';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Plugin detail documents without state: language chains, the `meta.detail` or README selection of a package, image
3
+ * destinations beside a document, and read-only file sources for local packages and published npm versions.
4
+ * @module @deepseek-ai/dsh-plugin-detail
5
+ */
6
+ export { DetailFailure, encodePath, fetchBody, joinPath, localFiles, NPM_FILE_SOURCES, npmFileSourceOrder, npmFiles, README_NAMES, readmeByName, readmeName, } from "./files.js";
7
+ export { detailImage, languageChain, markdownOf, readPackageDocument } from "./document.js";
8
+ export { detailImageResponse } from "./response.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,17 @@
1
+ /** HTTP responses of Host routes that serve images beside detail documents. */
2
+ import type { DetailFailureReason } from './types.ts';
3
+ /** An image read beside a detail document. */
4
+ export interface DetailImage {
5
+ readonly bytes: Uint8Array;
6
+ readonly mediaType: string;
7
+ }
8
+ /**
9
+ * The response of an image route: the image, 404 when there is none, or the failure's status with its reason as the
10
+ * body. Every response carries `X-Content-Type-Options: nosniff` and a sandbox content security policy, because an SVG
11
+ * opened directly would otherwise run scripts on the authenticated API origin; only an image gets `cacheControl`.
12
+ * @param outcome - the image, undefined when none exists, or why it cannot be read; `invalid` also answers a malformed request.
13
+ * @param cacheControl - the `Cache-Control` value of an image.
14
+ * @returns the response.
15
+ */
16
+ export declare function detailImageResponse(outcome: DetailImage | DetailFailureReason | undefined, cacheControl: string): Response;
17
+ //# sourceMappingURL=response.d.ts.map
@@ -0,0 +1,28 @@
1
+ /** HTTP status of each detail failure. */
2
+ const FAILURE_STATUS = {
3
+ 'too-large': 413, 'network': 502, 'denied': 403, 'git-unavailable': 503, 'invalid': 400,
4
+ };
5
+ /**
6
+ * The response of an image route: the image, 404 when there is none, or the failure's status with its reason as the
7
+ * body. Every response carries `X-Content-Type-Options: nosniff` and a sandbox content security policy, because an SVG
8
+ * opened directly would otherwise run scripts on the authenticated API origin; only an image gets `cacheControl`.
9
+ * @param outcome - the image, undefined when none exists, or why it cannot be read; `invalid` also answers a malformed request.
10
+ * @param cacheControl - the `Cache-Control` value of an image.
11
+ * @returns the response.
12
+ */
13
+ export function detailImageResponse(outcome, cacheControl) {
14
+ const [status, body, type] = typeof outcome === 'object'
15
+ // A copy into a fresh buffer is a body `Response` accepts whatever buffer the bytes view.
16
+ ? [200, new Uint8Array(outcome.bytes), outcome.mediaType]
17
+ : outcome === undefined ? [404, 'not found', undefined] : [FAILURE_STATUS[outcome], outcome, undefined];
18
+ return new Response(body, {
19
+ status,
20
+ headers: {
21
+ 'Content-Type': type ?? 'text/plain; charset=utf-8',
22
+ 'Cache-Control': status === 200 ? cacheControl : 'no-store',
23
+ 'X-Content-Type-Options': 'nosniff',
24
+ 'Content-Security-Policy': "sandbox; default-src 'none'; style-src 'unsafe-inline'",
25
+ },
26
+ });
27
+ }
28
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1,11 @@
1
+ /** Plugin detail records that Remote methods and their clients share. */
2
+ /**
3
+ * Why a detail document or one of its images cannot be read: `too-large` beyond a size limit, `network` when a source
4
+ * cannot be reached, `denied` when Git refuses the repository with the user's credentials, `git-unavailable` when a
5
+ * repository must be cloned and Git cannot run, and `invalid` for a malformed locale file or `meta.detail`, or a named
6
+ * file that does not exist.
7
+ */
8
+ export type DetailFailureReason = 'too-large' | 'network' | 'denied' | 'git-unavailable' | 'invalid';
9
+ /** A public CDN that serves single files of published npm package versions. */
10
+ export type NpmFileSource = 'jsdelivr' | 'unpkg' | 'npmmirror';
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ /** Plugin detail records that Remote methods and their clients share. */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,40 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-plugin-detail",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "description": "Plugin detail documents: meta.detail or README selection, image paths, and local and npm CDN file sources",
4
+ "version": "0.2.2-alpha.2",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/util/plugin-detail"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./types": {
22
+ "types": "./lib/types/types.d.ts",
23
+ "default": "./lib/types/types.js"
24
+ },
25
+ "./src/*": "./src/*",
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "lib/index.js",
30
+ "lib/types/**/*.js",
31
+ "lib/types/**/*.d.ts"
32
+ ],
33
+ "license": "MIT",
34
+ "peerDependencies": {
35
+ "@deepseek-ai/cordis": "~4.0.6-alpha.1"
36
+ },
37
+ "devDependencies": {
38
+ "@deepseek-ai/cordis": "~4.0.6-alpha.1"
39
+ }
6
40
  }