dsh-unplug 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/lib/cli.js +78 -13
- package/lib/index.js +14 -1
- package/lib/lib/remove.js +7 -2
- package/lib/lib/ux.js +36 -0
- package/lib/types/lib/ux.d.ts +11 -0
- package/package.json +70 -70
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 (2026-08-20)
|
|
4
|
+
|
|
5
|
+
- UX improvement: `fix` alias for `reconcile`(傻子也会用)。
|
|
6
|
+
- `remove --dry-run` — preview what would be removed without executing.
|
|
7
|
+
- Friendlier CLI help with `--dry-run` flag.
|
|
8
|
+
|
|
9
|
+
|
|
3
10
|
## 0.2.4 (2026-08-20)
|
|
4
11
|
|
|
5
12
|
- Fix CI: add `prepare` script (doctor requirement for git installs).
|
package/lib/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import { dshHome } from './lib/paths.js';
|
|
|
8
8
|
import { audit } from './lib/audit.js';
|
|
9
9
|
import { removePlugin, setPluginEnabled } from './lib/remove.js';
|
|
10
10
|
import { reconcile } from './lib/reconcile.js';
|
|
11
|
+
import { installedPlugins, listProfiles, resolveProfile } from './lib/ux.js';
|
|
11
12
|
function usage() {
|
|
12
13
|
return [
|
|
13
14
|
'dsh-unplug — 让 DSH 插件插拔自如 / plug/unplug any DeepSeek Harness plugin cleanly',
|
|
@@ -21,12 +22,15 @@ function usage() {
|
|
|
21
22
|
' disable <plugin> 禁用但不删除(移出 bundles,保留依赖) / disable without deleting',
|
|
22
23
|
' enable <plugin> 重新启用(加回 bundles,清除 disabled) / re-enable a disabled plugin',
|
|
23
24
|
' audit 检测孤立行/悬空 bundle / detect orphaned rows, dangling bundles',
|
|
24
|
-
' reconcile
|
|
25
|
+
' reconcile / fix 自动修复悬空与孤立状态 / auto-fix dangling bundles and orphan rows',
|
|
26
|
+
' remove <p> --dry-run 预览卸载内容 / preview what would be removed',
|
|
25
27
|
'',
|
|
26
28
|
'选项 / Options:',
|
|
27
29
|
' --profile <name> Profile 名(默认 default) / profile name',
|
|
28
30
|
' --home <path> DSH_HOME 路径(默认 env DSH_HOME 或 ~/.dsh) / DSH_HOME path',
|
|
29
31
|
' --yes 确认破坏性操作(remove/reconcile 需要) / confirm destructive ops',
|
|
32
|
+
' --dry-run 只预览不执行(remove/reconcile) / preview without executing',
|
|
33
|
+
' --all 对所有 profile 执行(list/audit) / act on all profiles',
|
|
30
34
|
' --json 输出机器可读 JSON / machine-readable JSON report',
|
|
31
35
|
' --help 显示帮助 / show this help',
|
|
32
36
|
'',
|
|
@@ -35,10 +39,11 @@ function usage() {
|
|
|
35
39
|
' dsh-unplug remove dsh-disk-audit --yes',
|
|
36
40
|
' dsh-unplug disable dsh-readme-forge --profile my-profile',
|
|
37
41
|
' dsh-unplug enable dsh-readme-forge --json',
|
|
42
|
+
' dsh-unplug list --all',
|
|
38
43
|
].join('\n');
|
|
39
44
|
}
|
|
40
45
|
function parseArgs(argv) {
|
|
41
|
-
const options = { command: '', profile: 'default', home: '', yes: false, json: false };
|
|
46
|
+
const options = { command: '', profile: 'default', home: '', yes: false, dryRun: false, all: false, json: false };
|
|
42
47
|
const positional = [];
|
|
43
48
|
for (let i = 0; i < argv.length; i++) {
|
|
44
49
|
const arg = argv[i];
|
|
@@ -51,6 +56,12 @@ function parseArgs(argv) {
|
|
|
51
56
|
case '--yes':
|
|
52
57
|
options.yes = true;
|
|
53
58
|
break;
|
|
59
|
+
case '--dry-run':
|
|
60
|
+
options.dryRun = true;
|
|
61
|
+
break;
|
|
62
|
+
case '--all':
|
|
63
|
+
options.all = true;
|
|
64
|
+
break;
|
|
54
65
|
case '--profile':
|
|
55
66
|
options.profile = argv[++i];
|
|
56
67
|
if (options.profile === undefined)
|
|
@@ -68,7 +79,7 @@ function parseArgs(argv) {
|
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
81
|
if (positional.length === 0)
|
|
71
|
-
return {
|
|
82
|
+
return { menu: true, ...options };
|
|
72
83
|
options.command = positional[0];
|
|
73
84
|
options.plugin = positional[1];
|
|
74
85
|
return options;
|
|
@@ -118,6 +129,17 @@ function printResult(value, json) {
|
|
|
118
129
|
}
|
|
119
130
|
export async function main(argv) {
|
|
120
131
|
const parsed = parseArgs(argv);
|
|
132
|
+
if ('menu' in parsed) {
|
|
133
|
+
console.log('dsh-unplug — 让 DSH 插件插拔自如 / plug/unplug any plugin cleanly');
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log('不知道做什么?直接输入下面任一命令:');
|
|
136
|
+
console.log(' dsh-unplug list 看看装了什么插件');
|
|
137
|
+
console.log(' dsh-unplug fix --yes 一键修复坏掉的插件状态');
|
|
138
|
+
console.log(' dsh-unplug remove <名字> --yes 卸载插件');
|
|
139
|
+
console.log(' dsh-unplug disable <名字> 临时禁用(不删除)');
|
|
140
|
+
console.log(' dsh-unplug --help 查看全部命令');
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
121
143
|
if ('help' in parsed) {
|
|
122
144
|
console.log(usage());
|
|
123
145
|
return 0;
|
|
@@ -127,22 +149,53 @@ export async function main(argv) {
|
|
|
127
149
|
console.error(usage());
|
|
128
150
|
return 2;
|
|
129
151
|
}
|
|
130
|
-
const { command, plugin, profile, home, yes, json } = parsed;
|
|
152
|
+
const { command, plugin, profile, home, yes, dryRun, all, json } = parsed;
|
|
131
153
|
const resolvedHome = home || dshHome();
|
|
132
154
|
try {
|
|
155
|
+
const resolved = resolveProfile(resolvedHome, profile);
|
|
156
|
+
const activeProfile = resolved.profile;
|
|
133
157
|
switch (command) {
|
|
134
158
|
case 'list':
|
|
135
159
|
case 'audit': {
|
|
136
|
-
|
|
137
|
-
|
|
160
|
+
if (all) {
|
|
161
|
+
const profiles = listProfiles(resolvedHome);
|
|
162
|
+
if (profiles.length === 0) {
|
|
163
|
+
console.error('没有找到任何 profile(目录 ' + resolvedHome + '\\profiles 为空)。先 `dsh plugin --profile default add <插件>` 创建一个。');
|
|
164
|
+
return 1;
|
|
165
|
+
}
|
|
166
|
+
let failed = false;
|
|
167
|
+
for (const name of profiles) {
|
|
168
|
+
try {
|
|
169
|
+
const result = audit(resolvedHome, name);
|
|
170
|
+
const code = printResult({ schema: 'dsh-unplug/v1', ok: true, ...result, command, profile: name }, json);
|
|
171
|
+
if (code !== 0)
|
|
172
|
+
failed = true;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error(`profile ${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
176
|
+
failed = true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return failed ? 1 : 0;
|
|
180
|
+
}
|
|
181
|
+
const result = audit(resolvedHome, activeProfile);
|
|
182
|
+
return printResult({ schema: 'dsh-unplug/v1', ok: true, ...result, command, profile: activeProfile }, json);
|
|
138
183
|
}
|
|
139
184
|
case 'reconcile': {
|
|
140
185
|
if (!yes) {
|
|
141
186
|
console.error('reconcile requires --yes to confirm');
|
|
142
187
|
return 2;
|
|
143
188
|
}
|
|
144
|
-
const result = reconcile(resolvedHome,
|
|
145
|
-
return printResult({ ...result, command }, json);
|
|
189
|
+
const result = reconcile(resolvedHome, activeProfile);
|
|
190
|
+
return printResult({ ...result, command, profile: activeProfile }, json);
|
|
191
|
+
}
|
|
192
|
+
case 'fix': {
|
|
193
|
+
if (!yes) {
|
|
194
|
+
console.error('fix requires --yes to confirm');
|
|
195
|
+
return 2;
|
|
196
|
+
}
|
|
197
|
+
const result = reconcile(resolvedHome, activeProfile);
|
|
198
|
+
return printResult({ ...result, command: 'reconcile', profile: activeProfile }, json);
|
|
146
199
|
}
|
|
147
200
|
case 'remove': {
|
|
148
201
|
if (!yes) {
|
|
@@ -150,11 +203,23 @@ export async function main(argv) {
|
|
|
150
203
|
return 2;
|
|
151
204
|
}
|
|
152
205
|
if (!plugin) {
|
|
153
|
-
|
|
206
|
+
const installed = installedPlugins(resolvedHome, activeProfile);
|
|
207
|
+
if (installed.length === 0) {
|
|
208
|
+
console.error(`profile "${activeProfile}" 里没有可卸载的插件。先 dsh-unplug list 看看。`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
console.error('你要卸载哪个?当前已装:');
|
|
212
|
+
for (const name of installed)
|
|
213
|
+
console.error(` dsh-unplug remove ${name} --yes`);
|
|
214
|
+
}
|
|
154
215
|
return 2;
|
|
155
216
|
}
|
|
156
|
-
|
|
157
|
-
|
|
217
|
+
if (dryRun) {
|
|
218
|
+
console.log(`[dry-run] 将卸载 "${plugin}" from profile "${activeProfile}"(bundles + 补丁行 + 依赖)`);
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
const result = removePlugin(resolvedHome, activeProfile, plugin, { force: yes });
|
|
222
|
+
return printResult({ ...result, command, profile: activeProfile }, json);
|
|
158
223
|
}
|
|
159
224
|
case 'disable':
|
|
160
225
|
case 'enable': {
|
|
@@ -162,8 +227,8 @@ export async function main(argv) {
|
|
|
162
227
|
console.error(`${command} requires a plugin name`);
|
|
163
228
|
return 2;
|
|
164
229
|
}
|
|
165
|
-
const result = setPluginEnabled(resolvedHome,
|
|
166
|
-
return printResult({ ...result, command }, json);
|
|
230
|
+
const result = setPluginEnabled(resolvedHome, activeProfile, plugin, command === 'enable');
|
|
231
|
+
return printResult({ ...result, command, profile: activeProfile }, json);
|
|
167
232
|
}
|
|
168
233
|
default:
|
|
169
234
|
console.error(`unknown command: ${command} (try --help)`);
|
package/lib/index.js
CHANGED
|
@@ -48,7 +48,7 @@ export function apply(ctx, config) {
|
|
|
48
48
|
command: {
|
|
49
49
|
type: 'string',
|
|
50
50
|
required: true,
|
|
51
|
-
enum: ['list', 'remove', 'disable', 'enable', 'audit', 'reconcile'],
|
|
51
|
+
enum: ['list', 'remove', 'disable', 'enable', 'audit', 'reconcile', 'fix'],
|
|
52
52
|
description: 'Action to perform / 要执行的操作',
|
|
53
53
|
},
|
|
54
54
|
plugin: {
|
|
@@ -121,6 +121,19 @@ export function apply(ctx, config) {
|
|
|
121
121
|
fixedRows: result.fixedRows,
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
+
case 'fix': {
|
|
125
|
+
if (!args.force)
|
|
126
|
+
return errorReport('UNPLUG_REQUIRES_FORCE', 'fix requires `force: true` to confirm the cleanup', profile, args.command);
|
|
127
|
+
const result = reconcile(home, profile);
|
|
128
|
+
return {
|
|
129
|
+
schema: result.schema,
|
|
130
|
+
ok: result.ok,
|
|
131
|
+
command: 'reconcile',
|
|
132
|
+
profile: result.profile,
|
|
133
|
+
fixedBundles: result.fixedBundles,
|
|
134
|
+
fixedRows: result.fixedRows,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
124
137
|
case 'remove': {
|
|
125
138
|
if (!args.force)
|
|
126
139
|
return errorReport('UNPLUG_REQUIRES_FORCE', 'Remove requires `force: true` to confirm the destructive operation', profile, args.command);
|
package/lib/lib/remove.js
CHANGED
|
@@ -7,6 +7,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
7
7
|
import { audit } from './audit.js';
|
|
8
8
|
import { parsePatch } from './patches.js';
|
|
9
9
|
import { resolveBundlePatchPath } from './resolve.js';
|
|
10
|
+
import { listProfiles } from './ux.js';
|
|
10
11
|
function resolvePlugin(home, profileDir, profileName, plugin) {
|
|
11
12
|
const manifest = readProfileManifest(profileDir);
|
|
12
13
|
const allBundles = [...(manifest.dsh?.profile?.bundles ?? []), ...(manifest.dsh?.profile?.disabledBundles ?? [])];
|
|
@@ -60,7 +61,9 @@ export function removePlugin(home, profileName, plugin, options) {
|
|
|
60
61
|
const profileDir = path.join(home, 'profiles', profileName);
|
|
61
62
|
const manifestPath = path.join(profileDir, 'package.json');
|
|
62
63
|
if (!existsSync(manifestPath)) {
|
|
63
|
-
|
|
64
|
+
const available = listProfiles(home);
|
|
65
|
+
throw new Error(`profile "${profileName}" not found at ${profileDir}`
|
|
66
|
+
+ (available.length > 0 ? `;可用 profiles: ${available.join(', ')}` : ';还没有任何 profile'));
|
|
64
67
|
}
|
|
65
68
|
const resolved = resolvePlugin(home, profileDir, profileName, plugin);
|
|
66
69
|
const pkgName = resolved.bundleName ?? plugin;
|
|
@@ -108,7 +111,9 @@ export function setPluginEnabled(home, profileName, plugin, enabled) {
|
|
|
108
111
|
const profileDir = path.join(home, 'profiles', profileName);
|
|
109
112
|
const manifestPath = path.join(profileDir, 'package.json');
|
|
110
113
|
if (!existsSync(manifestPath)) {
|
|
111
|
-
|
|
114
|
+
const available = listProfiles(home);
|
|
115
|
+
throw new Error(`profile "${profileName}" not found at ${profileDir}`
|
|
116
|
+
+ (available.length > 0 ? `;可用 profiles: ${available.join(', ')}` : ';还没有任何 profile'));
|
|
112
117
|
}
|
|
113
118
|
const resolved = resolvePlugin(home, profileDir, profileName, plugin);
|
|
114
119
|
const pkgName = resolved.bundleName ?? plugin;
|
package/lib/lib/ux.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { audit } from './audit.js';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve which profile to act on. If the requested profile is missing,
|
|
6
|
+
* fall back to the first real profile so novices do not need to know names.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveProfile(home, requested) {
|
|
9
|
+
const profiles = listProfiles(home);
|
|
10
|
+
if (profiles.includes(requested))
|
|
11
|
+
return { profile: requested, fallback: false };
|
|
12
|
+
if (profiles.length > 0)
|
|
13
|
+
return { profile: profiles[0], fallback: true };
|
|
14
|
+
throw new Error(`没有找到任何 profile(目录 ${path.join(home, 'profiles')} 为空)。`
|
|
15
|
+
+ ' 先运行 `dsh plugin --profile default add <插件>` 创建第一个。');
|
|
16
|
+
}
|
|
17
|
+
export function listProfiles(home) {
|
|
18
|
+
const dir = path.join(home, 'profiles');
|
|
19
|
+
if (!existsSync(dir))
|
|
20
|
+
return [];
|
|
21
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
22
|
+
.filter((entry) => entry.isDirectory() && existsSync(path.join(dir, entry.name, 'package.json')))
|
|
23
|
+
.map((entry) => entry.name)
|
|
24
|
+
.sort();
|
|
25
|
+
}
|
|
26
|
+
/** Human-friendly list of installed plugin names/ids for a profile. */
|
|
27
|
+
export function installedPlugins(home, profile) {
|
|
28
|
+
const result = audit(home, profile);
|
|
29
|
+
const names = new Set();
|
|
30
|
+
for (const row of result.rows) {
|
|
31
|
+
if (row.name !== undefined)
|
|
32
|
+
names.add(row.name);
|
|
33
|
+
names.add(row.id);
|
|
34
|
+
}
|
|
35
|
+
return [...names].sort();
|
|
36
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve which profile to act on. If the requested profile is missing,
|
|
3
|
+
* fall back to the first real profile so novices do not need to know names.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolveProfile(home: string, requested: string): {
|
|
6
|
+
profile: string;
|
|
7
|
+
fallback: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function listProfiles(home: string): string[];
|
|
10
|
+
/** Human-friendly list of installed plugin names/ids for a profile. */
|
|
11
|
+
export declare function installedPlugins(home: string, profile: string): string[];
|
package/package.json
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-unplug",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Plug/unplug any DeepSeek Harness plugin cleanly: list every mounted layer, disable/enable without deleting, remove bundles + patch rows + dependencies in one pass, and audit for orphaned/dangling plugin state. Zero runtime dependencies; read-only by default.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "lib/index.js",
|
|
7
|
-
"types": "lib/types/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"dsh-unplug": "lib/bin.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"lib",
|
|
13
|
-
"cordis.patch.yml",
|
|
14
|
-
"README.md",
|
|
15
|
-
"README.zh.md",
|
|
16
|
-
"SECURITY.md",
|
|
17
|
-
"CONTRIBUTING.md",
|
|
18
|
-
"CHANGELOG.md"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"prepare": "pnpm run build",
|
|
23
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:integration": "node scripts/integration-test.mjs"
|
|
26
|
-
},
|
|
27
|
-
"keywords": [
|
|
28
|
-
"dsh",
|
|
29
|
-
"dsh-plugin",
|
|
30
|
-
"plugin-manager",
|
|
31
|
-
"uninstall",
|
|
32
|
-
"lifecycle",
|
|
33
|
-
"unplug"
|
|
34
|
-
],
|
|
35
|
-
"peerDependencies": {
|
|
36
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
37
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
|
|
38
|
-
},
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
45
|
-
"@types/node": "^22.20.0",
|
|
46
|
-
"typescript": "^5.6.3",
|
|
47
|
-
"vitest": "^2.1.9"
|
|
48
|
-
},
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=18"
|
|
51
|
-
},
|
|
52
|
-
"pnpm": {
|
|
53
|
-
"onlyBuiltDependencies": [
|
|
54
|
-
"esbuild"
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
|
-
"dsh": {
|
|
58
|
-
"bundle": {
|
|
59
|
-
"patch": "./cordis.patch.yml"
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
"repository": {
|
|
63
|
-
"type": "git",
|
|
64
|
-
"url": "git+https://github.com/zoahdev/dsh-unplug.git"
|
|
65
|
-
},
|
|
66
|
-
"bugs": {
|
|
67
|
-
"url": "https://github.com/zoahdev/dsh-unplug/issues"
|
|
68
|
-
},
|
|
69
|
-
"homepage": "https://github.com/zoahdev/dsh-unplug"
|
|
70
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-unplug",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Plug/unplug any DeepSeek Harness plugin cleanly: list every mounted layer, disable/enable without deleting, remove bundles + patch rows + dependencies in one pass, and audit for orphaned/dangling plugin state. Zero runtime dependencies; read-only by default.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"dsh-unplug": "lib/bin.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"lib",
|
|
13
|
+
"cordis.patch.yml",
|
|
14
|
+
"README.md",
|
|
15
|
+
"README.zh.md",
|
|
16
|
+
"SECURITY.md",
|
|
17
|
+
"CONTRIBUTING.md",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"prepare": "pnpm run build",
|
|
23
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:integration": "node scripts/integration-test.mjs"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"dsh",
|
|
29
|
+
"dsh-plugin",
|
|
30
|
+
"plugin-manager",
|
|
31
|
+
"uninstall",
|
|
32
|
+
"lifecycle",
|
|
33
|
+
"unplug"
|
|
34
|
+
],
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
37
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
45
|
+
"@types/node": "^22.20.0",
|
|
46
|
+
"typescript": "^5.6.3",
|
|
47
|
+
"vitest": "^2.1.9"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18"
|
|
51
|
+
},
|
|
52
|
+
"pnpm": {
|
|
53
|
+
"onlyBuiltDependencies": [
|
|
54
|
+
"esbuild"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"dsh": {
|
|
58
|
+
"bundle": {
|
|
59
|
+
"patch": "./cordis.patch.yml"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "git+https://github.com/zoahdev/dsh-unplug.git"
|
|
65
|
+
},
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "https://github.com/zoahdev/dsh-unplug/issues"
|
|
68
|
+
},
|
|
69
|
+
"homepage": "https://github.com/zoahdev/dsh-unplug"
|
|
70
|
+
}
|