@noob-stupid/dsh-plugin-console 0.3.18 → 0.3.19
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/lib/client.js +35 -4
- package/lib/index.js +109 -7
- package/package.json +39 -39
package/lib/client.js
CHANGED
|
@@ -136,6 +136,7 @@ window.__ModuleLoader__.load({
|
|
|
136
136
|
loadingDetails: "正在读取详情…",
|
|
137
137
|
githubLoggedIn: "已登录 GitHub:",
|
|
138
138
|
githubCornerOut: "未登录 GitHub",
|
|
139
|
+
hubUpdateAvailable: "下载更新",
|
|
139
140
|
searchInstalledPlaceholder: "搜索已安装插件(名称或 id)",
|
|
140
141
|
extraFilter: "已装",
|
|
141
142
|
extraFilterAll: "全部",
|
|
@@ -370,6 +371,7 @@ window.__ModuleLoader__.load({
|
|
|
370
371
|
readmeLabel: "Readme summary",
|
|
371
372
|
loadingDetails: "Reading details…",
|
|
372
373
|
githubLoggedIn: "GitHub signed in: ",
|
|
374
|
+
hubUpdateAvailable: "Download update",
|
|
373
375
|
githubCornerOut: "Not signed in to GitHub",
|
|
374
376
|
searchInstalledPlaceholder: "Search installed plugins (name or id)",
|
|
375
377
|
extraFilter: "Installed",
|
|
@@ -763,7 +765,7 @@ window.__ModuleLoader__.load({
|
|
|
763
765
|
/** monorepo 子包列表:git trees 递归列出 packages 目录下的 package.json,逐个取 npm 包名(上限 24 个)。 */
|
|
764
766
|
async function fetchSubpackages(repo, branch) {
|
|
765
767
|
const data = await githubFetch(`https://api.github.com/repos/${encodeURIComponent(repo)}/git/trees/${encodeURIComponent(branch)}?recursive=1`);
|
|
766
|
-
const paths = (data.tree ?? []).filter((node) => node.type === "blob" && /^packages\/[^/]+\/package\.json$/u.test(node.path)).map((node) => node.path);
|
|
768
|
+
const paths = (data.tree ?? []).filter((node) => node.type === "blob" && /^(?:packages|examples|plugins|skills|apps|extensions|src|lib)\/[^/]+\/package\.json$/u.test(node.path)).map((node) => node.path);
|
|
767
769
|
if (paths.length === 0) return [];
|
|
768
770
|
const out = [];
|
|
769
771
|
for (const path of paths.slice(0, 24)) {
|
|
@@ -771,7 +773,7 @@ window.__ModuleLoader__.load({
|
|
|
771
773
|
if (text === null) continue;
|
|
772
774
|
try {
|
|
773
775
|
const pkg = JSON.parse(text);
|
|
774
|
-
if (pkg && typeof pkg.name === "string") out.push({ dir: path.split("/")[1], name: pkg.name });
|
|
776
|
+
if (pkg && typeof pkg.name === "string") out.push({ dir: path.split("/")[1], path: path.split("/").slice(0, -1).join("/"), name: pkg.name });
|
|
775
777
|
} catch {}
|
|
776
778
|
}
|
|
777
779
|
return out;
|
|
@@ -858,6 +860,8 @@ window.__ModuleLoader__.load({
|
|
|
858
860
|
const [frameworkUpgrading, setFrameworkUpgrading] = react.useState(false);
|
|
859
861
|
// 框架升级进度(重连后恢复显示):{status, message}
|
|
860
862
|
const [frameworkStatus, setFrameworkStatus] = react.useState(null);
|
|
863
|
+
// Hub 自身更新:仅在检测到远程新版时显示下载/更新按钮
|
|
864
|
+
const [selfUpdate, setSelfUpdate] = react.useState(null);
|
|
861
865
|
// 进度条步骤(与 host 脚本 SetState 的阶段对应)
|
|
862
866
|
const FW_STEPS = [
|
|
863
867
|
{ key: "starting", label: t("fwStepBackup") },
|
|
@@ -1066,6 +1070,22 @@ window.__ModuleLoader__.load({
|
|
|
1066
1070
|
};
|
|
1067
1071
|
run();
|
|
1068
1072
|
}, [market, state]);
|
|
1073
|
+
// Hub 自身更新检测:只在远程 npm 有更新时显示按钮
|
|
1074
|
+
react.useEffect(() => {
|
|
1075
|
+
if (state.status !== "ready") return;
|
|
1076
|
+
const current = state.data.selfVersion ?? null;
|
|
1077
|
+
if (!current) return;
|
|
1078
|
+
call("/plugin-console/check-update", { packageName: "@noob-stupid/dsh-plugin-console" }).then(
|
|
1079
|
+
(data) => {
|
|
1080
|
+
if (data && data.error === null && typeof data.latest === "string" && data.latest !== current) {
|
|
1081
|
+
setSelfUpdate({ latest: data.latest });
|
|
1082
|
+
} else {
|
|
1083
|
+
setSelfUpdate(null);
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1086
|
+
() => setSelfUpdate(null),
|
|
1087
|
+
);
|
|
1088
|
+
}, [state]);
|
|
1069
1089
|
// 搜索源菜单:点击外部收起
|
|
1070
1090
|
react.useEffect(() => {
|
|
1071
1091
|
if (!sourceMenuOpen) return;
|
|
@@ -1629,6 +1649,11 @@ window.__ModuleLoader__.load({
|
|
|
1629
1649
|
startSuiteJob(item);
|
|
1630
1650
|
return;
|
|
1631
1651
|
}
|
|
1652
|
+
if (item.subpackagePath && typeof item.packageName === "string" && item.packageName !== "") {
|
|
1653
|
+
// monorepo 子包:搜索结果带 packageName,按 npm 包名安装
|
|
1654
|
+
startJob(item.fullName, item.packageName, item.source ?? "github");
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1632
1657
|
startJob(item.fullName, null, item.source ?? "github");
|
|
1633
1658
|
};
|
|
1634
1659
|
/** 停用/启用已安装技能(写入官方调用策略 frontmatter,可逆)。 */
|
|
@@ -2073,8 +2098,8 @@ window.__ModuleLoader__.load({
|
|
|
2073
2098
|
onClick: () => doToggleSkill(detailSkillName, detailSkillDisabled),
|
|
2074
2099
|
}, togglingSkill === detailSkillName ? t("installingLocal") : (detailSkillDisabled ? t("skillEnable") : t("skillDisable")))
|
|
2075
2100
|
: null,
|
|
2076
|
-
info.privateRoot ? el("div", null,
|
|
2077
|
-
el("p", { className: styles.status, "data-error": "true" }, t("privateRootHint")),
|
|
2101
|
+
(info.privateRoot || !info.hasPackageJson) ? el("div", null,
|
|
2102
|
+
info.privateRoot ? el("p", { className: styles.status, "data-error": "true" }, t("privateRootHint")) : null,
|
|
2078
2103
|
el("p", { className: styles.status }, t("subpackagesTitle") + ":"),
|
|
2079
2104
|
subpackages === null ? null
|
|
2080
2105
|
: subpackages.status === "loading"
|
|
@@ -2159,6 +2184,12 @@ window.__ModuleLoader__.load({
|
|
|
2159
2184
|
? t("marketTitle")
|
|
2160
2185
|
: t("marketTitleOther").replace("{source}", sourceDisplayName(searchSource)))),
|
|
2161
2186
|
el("div", { id: "pc-ghwrap", className: styles.ghwrap },
|
|
2187
|
+
selfUpdate !== null ? el("button", {
|
|
2188
|
+
type: "button",
|
|
2189
|
+
className: styles.ghpill,
|
|
2190
|
+
title: t("hubUpdateAvailable") + " v" + selfUpdate.latest,
|
|
2191
|
+
onClick: () => window.open(`https://github.com/Noob-stupid/dsh-plugin-hub/releases/tag/v${selfUpdate.latest}`, "_blank")
|
|
2192
|
+
}, "⬇ " + t("hubUpdateAvailable") + " v" + selfUpdate.latest) : null,
|
|
2162
2193
|
el("button", {
|
|
2163
2194
|
type: "button",
|
|
2164
2195
|
className: styles.ghpill,
|
package/lib/index.js
CHANGED
|
@@ -1450,7 +1450,7 @@ async function fetchRepoPackage(repo, branch) {
|
|
|
1450
1450
|
* profile 目录由 pnpm 管理;若用 npm 写入会与 pnpm 的目录重建互相破坏
|
|
1451
1451
|
* (曾导致入口链接丢失、DSH 启动崩溃)。registry 走国内镜像。
|
|
1452
1452
|
*/
|
|
1453
|
-
async function pnpmInstall(profileDir, spec, registry = 'https://registry.npmmirror.com', timeout = 90000) {
|
|
1453
|
+
async function pnpmInstall(profileDir, spec, registry = 'https://registry.npmmirror.com', timeout = 90000, signal = null) {
|
|
1454
1454
|
const args = ['pnpm', 'add', spec, '--registry', registry]
|
|
1455
1455
|
const opts = {
|
|
1456
1456
|
cwd: profileDir,
|
|
@@ -1486,7 +1486,7 @@ async function pnpmInstall(profileDir, spec, registry = 'https://registry.npmmir
|
|
|
1486
1486
|
* 零依赖包可完整安装;带依赖包记录未补齐列表(不阻塞,供面板提示)。
|
|
1487
1487
|
* 返回 { version, missingDeps };失败抛错由调用方落入 next 通道。
|
|
1488
1488
|
*/
|
|
1489
|
-
async function curlManualInstall(profileDir, packageName, registries) {
|
|
1489
|
+
async function curlManualInstall(profileDir, packageName, registries, signal = null) {
|
|
1490
1490
|
let meta = null
|
|
1491
1491
|
let metaError = null
|
|
1492
1492
|
for (const reg of registries) {
|
|
@@ -1509,8 +1509,8 @@ async function curlManualInstall(profileDir, packageName, registries) {
|
|
|
1509
1509
|
mkdirSync(tmp, { recursive: true })
|
|
1510
1510
|
try {
|
|
1511
1511
|
const tgz = join(tmp, 'pkg.tgz')
|
|
1512
|
-
await execFileAsync(bin, ['-s', '-L', '-m', '60', '-o', tgz, tarball], { timeout: 70000, windowsHide: true })
|
|
1513
|
-
await execFileAsync('tar', ['-xzf', tgz, '-C', tmp], { timeout: 30000, windowsHide: true })
|
|
1512
|
+
await execFileAsync(bin, ['-s', '-L', '-m', '60', '-o', tgz, tarball], { timeout: 70000, windowsHide: true, ...(signal ? { signal } : {}) })
|
|
1513
|
+
await execFileAsync('tar', ['-xzf', tgz, '-C', tmp], { timeout: 30000, windowsHide: true, ...(signal ? { signal } : {}) })
|
|
1514
1514
|
const pkgPath = join(tmp, 'package')
|
|
1515
1515
|
// 盒子实验:解压后先验证,通过才覆盖正式位置(失败保留旧版本,服务不中断)
|
|
1516
1516
|
const box = verifyPackageBox(pkgPath, profileDir, packageName)
|
|
@@ -1532,6 +1532,34 @@ async function curlManualInstall(profileDir, packageName, registries) {
|
|
|
1532
1532
|
}
|
|
1533
1533
|
}
|
|
1534
1534
|
|
|
1535
|
+
/** 安装通道并行竞速:pnpm 与 curl 同时尝试,先成功者生效;失败方被 abort 不干扰。 */
|
|
1536
|
+
async function raceInstallChannels(profileDir, name, registries) {
|
|
1537
|
+
const controller = new AbortController()
|
|
1538
|
+
const signal = controller.signal
|
|
1539
|
+
const pnpmTask = (async () => {
|
|
1540
|
+
let lastError = null
|
|
1541
|
+
for (const registry of registries) {
|
|
1542
|
+
try {
|
|
1543
|
+
await pnpmInstall(profileDir, name, registry, 90000, signal)
|
|
1544
|
+
return { channel: 'pnpm', info: null }
|
|
1545
|
+
} catch (error) {
|
|
1546
|
+
lastError = error
|
|
1547
|
+
if (signal.aborted) throw error
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
throw lastError ?? new Error('pnpm 通道失败')
|
|
1551
|
+
})()
|
|
1552
|
+
const curlTask = (async () => {
|
|
1553
|
+
const info = await curlManualInstall(profileDir, name, registries, signal)
|
|
1554
|
+
return { channel: 'curl', info }
|
|
1555
|
+
})()
|
|
1556
|
+
const waitSuccess = (promise) => promise.then((value) => ({ value }), () => new Promise(() => {}))
|
|
1557
|
+
const timeout = new Promise((resolve) => setTimeout(() => resolve(null), 120000))
|
|
1558
|
+
const winner = await Promise.race([waitSuccess(pnpmTask), waitSuccess(curlTask), timeout])
|
|
1559
|
+
controller.abort()
|
|
1560
|
+
return winner ? winner.value : null
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1535
1563
|
/**
|
|
1536
1564
|
* 盒子实验验证:解压后的包目录先通过静态校验再允许覆盖正式位置。
|
|
1537
1565
|
* - package.json 必须可解析且 name 与安装目标一致
|
|
@@ -2208,7 +2236,7 @@ async function fetchSubpackageNames(repo, branch, auth) {
|
|
|
2208
2236
|
try {
|
|
2209
2237
|
const data = await githubJson(`${GITHUB_API}/repos/${repo}/git/trees/${encodeURIComponent(branch)}?recursive=1`, undefined, auth)
|
|
2210
2238
|
const paths = (data.tree ?? [])
|
|
2211
|
-
.filter((node) => node.type === 'blob' && /^packages\/[^/]+\/package\.json$/u.test(node.path))
|
|
2239
|
+
.filter((node) => node.type === 'blob' && /^(?:packages|examples|plugins|skills|apps|extensions|src|lib)\/[^/]+\/package\.json$/u.test(node.path))
|
|
2212
2240
|
.map((node) => node.path)
|
|
2213
2241
|
// 并行读取:黑洞期单条最坏 40s,24 条串行会拖到十几分钟
|
|
2214
2242
|
const results = await Promise.all(paths.slice(0, 24).map(async (path) => {
|
|
@@ -2216,7 +2244,7 @@ async function fetchSubpackageNames(repo, branch, auth) {
|
|
|
2216
2244
|
if (bodyText === null) return null
|
|
2217
2245
|
try {
|
|
2218
2246
|
const pkg = JSON.parse(bodyText)
|
|
2219
|
-
if (pkg && typeof pkg.name === 'string') return { dir: path.split('/')[1], name: pkg.name }
|
|
2247
|
+
if (pkg && typeof pkg.name === 'string') return { dir: path.split('/')[1], path: path.split('/').slice(0, -1).join('/'), name: pkg.name }
|
|
2220
2248
|
} catch {}
|
|
2221
2249
|
return null
|
|
2222
2250
|
}))
|
|
@@ -2431,6 +2459,32 @@ async function runInstallJob(job, ctx) {
|
|
|
2431
2459
|
for (let index = 0; index < candidates.length && installedName === null; index += 1) {
|
|
2432
2460
|
if (Date.now() > deadline) break
|
|
2433
2461
|
const name = candidates[index]
|
|
2462
|
+
// 加法优化:包已在 node_modules 且名字匹配时,不再重复安装/触发 EPERM,直接进入启用流程
|
|
2463
|
+
if (installedName === null) {
|
|
2464
|
+
const existingTarget = join(profileDir, 'node_modules', name, 'package.json')
|
|
2465
|
+
if (existsSync(existingTarget)) {
|
|
2466
|
+
try {
|
|
2467
|
+
const existingPkg = JSON.parse(readFileSync(existingTarget, 'utf8'))
|
|
2468
|
+
if (existingPkg && existingPkg.name === name) {
|
|
2469
|
+
installedName = name
|
|
2470
|
+
job.curlNote = `已检测到本地已安装 ${name}@${existingPkg.version ?? '?'},跳过重复下载`
|
|
2471
|
+
}
|
|
2472
|
+
} catch {}
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
// 加法并行竞速:pnpm 与 curl 同时启动,先成功者生效;失败方 abort,不影响后续串行通道
|
|
2476
|
+
if (installedName === null && !subpackageMode && !expanded) {
|
|
2477
|
+
const raced = await raceInstallChannels(profileDir, name, registries)
|
|
2478
|
+
if (raced) {
|
|
2479
|
+
installedName = name
|
|
2480
|
+
if (raced.channel === 'curl') {
|
|
2481
|
+
const racedInfo = raced.info
|
|
2482
|
+
const stillMissing = await backfillMissingDeps(profileDir, racedInfo.missingDeps, registries)
|
|
2483
|
+
job.curlNote = `已通过并行 curl 通道安装 v${racedInfo.version}${stillMissing.length > 0 ? `(依赖仍未补齐:${stillMissing.join('、')},网络恢复后建议重新安装)` : '(捆绑依赖已补齐)'}`
|
|
2484
|
+
if (racedInfo.boxNote) job.curlNote += `(盒子验证:${racedInfo.boxNote})`
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2434
2488
|
// 通道 1..n:配置的软件源依次尝试(每源 90 秒封顶)
|
|
2435
2489
|
for (let ri = 0; ri < registries.length && installedName === null; ri += 1) {
|
|
2436
2490
|
try {
|
|
@@ -2677,7 +2731,13 @@ async function handle(ctx, req, res) {
|
|
|
2677
2731
|
// 框架升级检测与适配(备份快照 + 重打框架补丁),try 包裹不阻塞 state 返回
|
|
2678
2732
|
let framework = null
|
|
2679
2733
|
try { framework = detectFrameworkUpgrade(ctx) } catch {}
|
|
2680
|
-
|
|
2734
|
+
let selfVersion = null
|
|
2735
|
+
try {
|
|
2736
|
+
const selfRequire = createRequire(import.meta.url)
|
|
2737
|
+
const selfPkg = JSON.parse(readFileSync(selfRequire.resolve('../package.json'), 'utf8'))
|
|
2738
|
+
selfVersion = typeof selfPkg.version === 'string' ? selfPkg.version : null
|
|
2739
|
+
} catch {}
|
|
2740
|
+
sendJson(res, 200, { ok: true, entries, patchPath, compat, installJobs: jobs, recentFailures, github: { loggedIn: auth.loggedIn, login: auth.login }, patch: { disables: patch.disables, forced: patch.forced, inserts: patch.inserts }, framework, selfVersion })
|
|
2681
2741
|
return
|
|
2682
2742
|
}
|
|
2683
2743
|
|
|
@@ -3035,6 +3095,48 @@ async function handle(ctx, req, res) {
|
|
|
3035
3095
|
)
|
|
3036
3096
|
items = normalizePlatformItems(data.items ?? [], 'main').map((item) => ({ ...item, source: 'github' }))
|
|
3037
3097
|
items = await enrichItems(items)
|
|
3098
|
+
// monorepo 子包增强(OpenViking/examples/dsh-memory-plugin 等可按子包名搜到)
|
|
3099
|
+
if (raw !== '' && !body.skills) {
|
|
3100
|
+
try {
|
|
3101
|
+
const codeData = await githubJson(
|
|
3102
|
+
`${GITHUB_API}/search/code?q=${encodeURIComponent(`${raw} filename:package.json`)}`,
|
|
3103
|
+
req.signal,
|
|
3104
|
+
auth.token,
|
|
3105
|
+
)
|
|
3106
|
+
const subItems = []
|
|
3107
|
+
for (const hit of (codeData.items ?? []).slice(0, 10)) {
|
|
3108
|
+
const hitPath = typeof hit.path === 'string' ? hit.path : ''
|
|
3109
|
+
if (!/^(?:packages|examples|plugins|skills|apps|extensions|src|lib)\/[^/]+\/package\.json$/u.test(hitPath)) continue
|
|
3110
|
+
const repoName = hit.repository?.full_name ?? ''
|
|
3111
|
+
if (!repoName) continue
|
|
3112
|
+
const dir = hitPath.split('/').slice(0, -1).join('/')
|
|
3113
|
+
let packageName = dir.split('/').slice(-1)[0]
|
|
3114
|
+
try {
|
|
3115
|
+
const pkgText = await rawTextWithFallback(repoName, 'main', hitPath)
|
|
3116
|
+
if (pkgText !== null) {
|
|
3117
|
+
const pkg = JSON.parse(pkgText)
|
|
3118
|
+
if (pkg && typeof pkg.name === 'string') packageName = pkg.name
|
|
3119
|
+
}
|
|
3120
|
+
} catch {}
|
|
3121
|
+
subItems.push({
|
|
3122
|
+
fullName: repoName,
|
|
3123
|
+
description: `子包:${dir}`,
|
|
3124
|
+
htmlUrl: `https://github.com/${repoName}/tree/main/${dir}`,
|
|
3125
|
+
stars: 0,
|
|
3126
|
+
updatedAt: '',
|
|
3127
|
+
defaultBranch: 'main',
|
|
3128
|
+
topics: [],
|
|
3129
|
+
source: 'github',
|
|
3130
|
+
subpackagePath: dir,
|
|
3131
|
+
packageName,
|
|
3132
|
+
})
|
|
3133
|
+
if (subItems.length >= 5) break
|
|
3134
|
+
}
|
|
3135
|
+
for (const sub of subItems) {
|
|
3136
|
+
if (!items.some((x) => x.fullName === sub.fullName)) items.push(sub)
|
|
3137
|
+
}
|
|
3138
|
+
} catch {}
|
|
3139
|
+
}
|
|
3038
3140
|
}
|
|
3039
3141
|
items = items.filter((item) => item.fullName !== '')
|
|
3040
3142
|
sendJson(res, 200, { ok: true, query, items, authenticated: auth.loggedIn, source })
|
package/package.json
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "DSH plugin management panel & marketplace: one-click enable/disable, multi-source market (GitHub/Gitee/custom), static-index market (500+ plugins / 300 skills), skills, suites, and one-click framework upgrade.",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "https://github.com/Noob-stupid/dsh-plugin-hub"
|
|
8
|
-
},
|
|
9
|
-
"type": "module",
|
|
10
|
-
"main": "./lib/index.js",
|
|
11
|
-
"exports": {
|
|
12
|
-
".": "./lib/index.js",
|
|
13
|
-
"./client": "./lib/client.js",
|
|
14
|
-
"./package.json": "./package.json"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"dsh-plugin",
|
|
18
|
-
"deepseek-harness",
|
|
19
|
-
"plugin-manager"
|
|
20
|
-
],
|
|
21
|
-
"dsh": {
|
|
22
|
-
"bundle": {
|
|
23
|
-
"patch": "./cordis.patch.yml"
|
|
24
|
-
},
|
|
25
|
-
"client": {
|
|
26
|
-
"platform": "web",
|
|
27
|
-
"inject": [
|
|
28
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
29
|
-
"@deepseek-ai/dsh-client-locale",
|
|
30
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"files": [
|
|
35
|
-
"lib",
|
|
36
|
-
"cordis.patch.yml"
|
|
37
|
-
],
|
|
38
|
-
"license": "MIT"
|
|
39
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
+
"version": "0.3.19",
|
|
4
|
+
"description": "DSH plugin management panel & marketplace: one-click enable/disable, multi-source market (GitHub/Gitee/custom), static-index market (500+ plugins / 300 skills), skills, suites, and one-click framework upgrade.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Noob-stupid/dsh-plugin-hub"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./lib/index.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./lib/index.js",
|
|
13
|
+
"./client": "./lib/client.js",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"dsh-plugin",
|
|
18
|
+
"deepseek-harness",
|
|
19
|
+
"plugin-manager"
|
|
20
|
+
],
|
|
21
|
+
"dsh": {
|
|
22
|
+
"bundle": {
|
|
23
|
+
"patch": "./cordis.patch.yml"
|
|
24
|
+
},
|
|
25
|
+
"client": {
|
|
26
|
+
"platform": "web",
|
|
27
|
+
"inject": [
|
|
28
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
29
|
+
"@deepseek-ai/dsh-client-locale",
|
|
30
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"lib",
|
|
36
|
+
"cordis.patch.yml"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|