dsh-plugin-pack 1.0.6 → 1.0.8

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.
Files changed (2) hide show
  1. package/client.js +253 -72
  2. package/package.json +1 -1
package/client.js CHANGED
@@ -113,11 +113,24 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
113
113
  'import.checking': '正在检查冲突…',
114
114
  'import.downloading': '正在从网络下载…',
115
115
  'net.title': '从网络安装',
116
- 'net.desc': '支持 GitHub 仓库 / Release / 直链,或 npm 包名。下载后会校验是不是整合包。',
117
- 'net.placeholder': 'https://github.com/用户/仓库 或 dsh-plugin-pack 或 https://.../x.zip',
116
+ 'net.desc': '输入插件整合包的来源:GitHub 仓库 / Release / 直链,或 npm 包名。下载后会校验它是不是整合包。',
117
+ 'net.placeholder': '例如 dsh-plugin-pack 或 https://github.com/用户/仓库',
118
118
  'net.go': '下载并安装',
119
119
  'net.running': '正在处理…',
120
120
  'net.notBundle': '下载到的不是整合包',
121
+ 'net.button': '添加整合包',
122
+ 'net.dialogTitle': '添加整合包',
123
+ 'net.install': '下载并安装',
124
+ 'net.close': '关闭',
125
+ 'net.examples': '来源示例',
126
+ 'net.ex1': '下载仓库归档',
127
+ 'net.ex2': '取该 Release 里的 zip 附件',
128
+ 'net.ex3': '任意直链',
129
+ 'net.ex4': 'npm 包(单插件)',
130
+ 'net.warnTitle': '安装前请确认来源可信',
131
+ 'net.warnBody': '整合包会覆盖已装插件的文件与配置,来源不明的包可能损坏 DeepSeek Harness。安装前会先列出重名插件,由你逐个决定覆盖还是跳过。',
132
+ 'net.done': '下载完成,已导入',
133
+ 'import.pageTitle': '导入插件整合包',
121
134
  'drop.title': '把 zip / tgz 或插件文件夹拖到这里',
122
135
  'drop.release': '松手就导入',
123
136
  'drop.running': '正在导入…',
@@ -282,11 +295,24 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
282
295
  'import.checking': 'Checking for conflicts…',
283
296
  'import.downloading': 'Downloading…',
284
297
  'net.title': 'Install from network',
285
- 'net.desc': 'GitHub repo / release / direct link, or an npm package name. We verify it is a bundle after download.',
286
- 'net.placeholder': 'https://github.com/user/repo · dsh-plugin-pack · https://.../x.zip',
298
+ 'net.desc': 'Enter a bundle source: GitHub repo / release / direct link, or an npm package name. We verify it is a bundle after download.',
299
+ 'net.placeholder': 'e.g. dsh-plugin-pack or https://github.com/user/repo',
287
300
  'net.go': 'Download and install',
288
301
  'net.running': 'Working…',
289
302
  'net.notBundle': 'Downloaded file is not a bundle',
303
+ 'net.button': 'Add bundle',
304
+ 'net.dialogTitle': 'Add bundle',
305
+ 'net.install': 'Download and install',
306
+ 'net.close': 'Close',
307
+ 'net.examples': 'Source examples',
308
+ 'net.ex1': 'download repo archive',
309
+ 'net.ex2': 'pick the zip asset of that release',
310
+ 'net.ex3': 'any direct link',
311
+ 'net.ex4': 'npm package (single plugin)',
312
+ 'net.warnTitle': 'Verify the source before installing',
313
+ 'net.warnBody': 'A bundle overwrites installed plugins and their config. Untrusted sources can damage DeepSeek Harness. You will be asked per-plugin whether to overwrite or skip.',
314
+ 'net.done': 'Downloaded and imported',
315
+ 'import.pageTitle': 'Import plugin bundle',
290
316
  'drop.title': 'Drop a zip / tgz or plugin folder here',
291
317
  'drop.release': 'Release to import',
292
318
  'drop.running': 'Importing…',
@@ -1287,6 +1313,191 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
1287
1313
  * @param {() => void} props.onCancel
1288
1314
  * @param {(msg: string) => string} props.t
1289
1315
  */
1316
+ /**
1317
+ * 「添加整合包」弹窗。
1318
+ *
1319
+ * 布局对齐 DSH 自带的「添加插件」:
1320
+ * 标题 → 说明 → 输入框 → 折叠的示例 → 提示块 → 大按钮
1321
+ *
1322
+ * 下载后会校验是不是整合包;不是就当场用醒目样式报出来,
1323
+ * 不会让你以为"装上了"结果其实是普通压缩包。
1324
+ *
1325
+ * @param {object} props
1326
+ * @param {boolean} props.open
1327
+ * @param {string} props.value 输入框内容
1328
+ * @param {(v: string) => void} props.onChange
1329
+ * @param {object|null} props.result 上一次下载的结果或错误
1330
+ * @param {boolean} props.busy
1331
+ * @param {string} props.phase 进度文案
1332
+ * @param {() => void} props.onInstall
1333
+ * @param {() => void} props.onClose
1334
+ * @param {(key: string) => string} props.t
1335
+ */
1336
+ function AddBundleDialog({ open, value, onChange, result, busy, phase, onInstall, onClose, t }) {
1337
+ const [showExamples, setShowExamples] = useState(false);
1338
+
1339
+ // Esc 关闭
1340
+ useEffect(() => {
1341
+ if (!open) return;
1342
+ const onKey = (event) => {
1343
+ if (event.key === 'Escape' && !busy) onClose();
1344
+ };
1345
+ window.addEventListener('keydown', onKey);
1346
+ return () => window.removeEventListener('keydown', onKey);
1347
+ }, [open, busy, onClose]);
1348
+
1349
+ if (!open) return null;
1350
+
1351
+ const isNotBundle =
1352
+ ['NOT_A_BUNDLE', 'NOT_A_ZIP', 'BAD_FORMAT', 'BAD_MANIFEST', 'BAD_PACK'].includes(String(result?.code ?? '')) ||
1353
+ /不是整合包|没有 manifest|不是插件包/i.test(String(result?.error ?? ''));
1354
+
1355
+ return h(
1356
+ 'div',
1357
+ {
1358
+ style: {
1359
+ position: 'fixed',
1360
+ inset: 0,
1361
+ zIndex: 10070,
1362
+ background: 'rgba(0,0,0,.45)',
1363
+ display: 'flex',
1364
+ alignItems: 'center',
1365
+ justifyContent: 'center',
1366
+ padding: 16,
1367
+ },
1368
+ // 点遮罩关闭(跑的时候不关,避免误触中断)
1369
+ onClick: () => !busy && onClose(),
1370
+ },
1371
+ h(
1372
+ 'div',
1373
+ {
1374
+ style: {
1375
+ width: 'min(560px, 100%)',
1376
+ background: 'var(--dsw-alias-bg-layer-1,#fff)',
1377
+ borderRadius: 14,
1378
+ padding: '20px 20px 16px',
1379
+ boxShadow: '0 12px 40px rgba(0,0,0,.22)',
1380
+ border: '.5px solid var(--dsw-alias-border-l1,#e6e6e6)',
1381
+ },
1382
+ onClick: (event) => event.stopPropagation(),
1383
+ },
1384
+ // 标题行 + 关闭
1385
+ h(
1386
+ 'div',
1387
+ { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 } },
1388
+ h('h2', { style: { margin: 0, fontSize: 17, fontWeight: 600, flex: 1 } }, t('net.dialogTitle')),
1389
+ h(
1390
+ 'button',
1391
+ {
1392
+ className: 'pp-btn sm',
1393
+ style: { flex: 'none', padding: '2px 8px' },
1394
+ disabled: busy,
1395
+ onClick: onClose,
1396
+ title: t('net.close'),
1397
+ },
1398
+ '✕',
1399
+ ),
1400
+ ),
1401
+ h('p', { className: 'pp-hint', style: { margin: '0 0 12px' } }, t('net.desc')),
1402
+
1403
+ // 输入框(自动聚焦,回车即安装)
1404
+ h('input', {
1405
+ className: 'pp-input pp-mono',
1406
+ type: 'text',
1407
+ autoFocus: true,
1408
+ value,
1409
+ placeholder: t('net.placeholder'),
1410
+ disabled: busy,
1411
+ onInput: (event) => onChange(event.target.value),
1412
+ onKeyDown: (event) => {
1413
+ if (event.key === 'Enter' && !busy && value.trim()) onInstall();
1414
+ },
1415
+ style: { width: '100%', boxSizing: 'border-box', fontSize: 12.5, padding: '9px 11px' },
1416
+ }),
1417
+
1418
+ // 折叠的示例(对齐自带弹窗的「安装引导和示例」)
1419
+ h(
1420
+ 'div',
1421
+ { style: { margin: '10px 0 0' } },
1422
+ h(
1423
+ 'button',
1424
+ {
1425
+ className: 'pp-btn sm',
1426
+ style: { padding: '2px 0', background: 'none', border: 'none', color: 'var(--dsw-alias-label-secondary,#6b7280)' },
1427
+ onClick: () => setShowExamples((v) => !v),
1428
+ },
1429
+ `${showExamples ? '▾' : '▸'} ${t('net.examples')}`,
1430
+ ),
1431
+ showExamples
1432
+ ? h(
1433
+ 'div',
1434
+ { className: 'pp-hint', style: { marginTop: 6, lineHeight: 1.9 } },
1435
+ h('div', null, h('code', null, 'https://github.com/用户/仓库'), ` ${t('net.ex1')}`),
1436
+ h('div', null, h('code', null, 'https://github.com/用户/仓库/releases/tag/v1.0.0'), ` ${t('net.ex2')}`),
1437
+ h('div', null, h('code', null, 'https://example.com/backup.zip'), ` ${t('net.ex3')}`),
1438
+ h('div', null, h('code', null, 'dsh-plugin-pack'), ` ${t('net.ex4')}`),
1439
+ )
1440
+ : null,
1441
+ ),
1442
+
1443
+ // 提示块(对齐自带的黄色提示)
1444
+ h(
1445
+ 'div',
1446
+ {
1447
+ style: {
1448
+ marginTop: 12,
1449
+ padding: '10px 12px',
1450
+ borderRadius: 10,
1451
+ background: 'color-mix(in srgb,var(--dsw-alias-state-warning-primary,#d97706) 8%,transparent)',
1452
+ border: '.5px solid color-mix(in srgb,var(--dsw-alias-state-warning-primary,#d97706) 35%,transparent)',
1453
+ fontSize: 12,
1454
+ lineHeight: 1.7,
1455
+ color: 'var(--dsw-alias-label-secondary,#6b7280)',
1456
+ },
1457
+ },
1458
+ h('div', { style: { fontWeight: 600, marginBottom: 2 } }, `⚠ ${t('net.warnTitle')}`),
1459
+ h('div', null, t('net.warnBody')),
1460
+ ),
1461
+
1462
+ // 结果区:成功 / 不是整合包 / 其它错误
1463
+ result
1464
+ ? h(
1465
+ 'div',
1466
+ { style: { marginTop: 12 } },
1467
+ result.error
1468
+ ? isNotBundle
1469
+ ? h(
1470
+ 'div',
1471
+ { className: 'pp-not-bundle' },
1472
+ h('div', { className: 'pp-not-bundle-title' }, t('net.notBundle')),
1473
+ h('div', { className: 'pp-not-bundle-detail' }, String(result.error)),
1474
+ )
1475
+ : h(Alert, { kind: 'err' }, String(result.error))
1476
+ : h(
1477
+ 'div',
1478
+ { className: 'pp-hint' },
1479
+ `✓ ${t('net.done')} · ${result.from ?? ''} · ${result.name ?? ''} · ${
1480
+ result.bytes ? (result.bytes / 1048576).toFixed(1) + ' MiB' : ''
1481
+ } · ${result.plugins?.length ?? 0} ${t('plugins')}`,
1482
+ ),
1483
+ )
1484
+ : null,
1485
+
1486
+ // 大按钮(对齐自带的整宽「安装」)
1487
+ h(
1488
+ 'button',
1489
+ {
1490
+ className: 'pp-btn primary',
1491
+ style: { width: '100%', marginTop: 14, padding: '10px 12px', boxSizing: 'border-box' },
1492
+ disabled: busy || !value.trim(),
1493
+ onClick: onInstall,
1494
+ },
1495
+ busy ? h(Spinner, { label: phase || t('net.running') }) : t('net.install'),
1496
+ ),
1497
+ ),
1498
+ );
1499
+ }
1500
+
1290
1501
  function ConflictDialog({ pending, onConfirm, onCancel, t }) {
1291
1502
  const conflicts = pending?.conflicts ?? [];
1292
1503
  /** 初始全部选「覆盖」——多数人是想升级到新版本。 */
@@ -1611,6 +1822,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
1611
1822
  const [netSource, setNetSource] = useState('');
1612
1823
  /** 网络安装的结果/错误。 */
1613
1824
  const [netResult, setNetResult] = useState(null);
1825
+ /** 「添加整合包」弹窗是否打开。 */
1826
+ const [netOpen, setNetOpen] = useState(false);
1614
1827
  /** 后台任务列表:切走画面回来靠它恢复 */
1615
1828
  const [jobs, setJobs] = useState([]);
1616
1829
  /** 体积上限(MiB),0 = 不限制。默认跟着服务端配置走。 */
@@ -1941,6 +2154,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
1941
2154
  setImportResult(result);
1942
2155
  await load();
1943
2156
  await refreshJobs();
2157
+ // 装完关掉弹窗,回到列表看结果
2158
+ setNetOpen(false);
1944
2159
  return;
1945
2160
  }
1946
2161
 
@@ -1956,15 +2171,8 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
1956
2171
  conflicts,
1957
2172
  plugins: preview.plugins ?? [],
1958
2173
  });
1959
- setNetResult({
1960
- ok: true,
1961
- downloaded: true,
1962
- file: fetched.file,
1963
- from: fetched.from,
1964
- name: fetched.name,
1965
- bytes: fetched.bytes,
1966
- plugins: fetched.plugins,
1967
- });
2174
+ // 交给冲突弹窗接管,先关掉来源弹窗
2175
+ setNetOpen(false);
1968
2176
  return;
1969
2177
  }
1970
2178
 
@@ -2117,6 +2325,25 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
2117
2325
  hotBusy ? h(Spinner, { label: t('hotload.running') }) : t('hotload'),
2118
2326
  ),
2119
2327
  h('button', { className: 'pp-btn sm', disabled: busy, onClick: load }, busy ? h(Spinner, { label: t('loading') }) : t('refresh')),
2328
+ /* 「添加整合包」放在这一行最右,对齐 DSH 自带的「添加插件」位置
2329
+ * (页面标题行右上角),而不是沉到「导入插件整合包」小标题旁边。
2330
+ * 只在导入页出现,其它子页不占位。 */
2331
+ onlyTab === 'import' || tab === 'import'
2332
+ ? h(
2333
+ 'button',
2334
+ {
2335
+ className: 'pp-btn sm',
2336
+ style: { display: 'inline-flex', alignItems: 'center', gap: 5 },
2337
+ disabled: busy,
2338
+ onClick: () => {
2339
+ setNetResult(null);
2340
+ setNetOpen(true);
2341
+ },
2342
+ },
2343
+ h('span', { style: { fontSize: 14, lineHeight: 1 } }, '+'),
2344
+ t('net.button'),
2345
+ )
2346
+ : null,
2120
2347
  ),
2121
2348
  error ? h(Alert, { kind: 'err' }, `${t('failed')}: ${error}`) : null,
2122
2349
  hotResult
@@ -2344,65 +2571,6 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
2344
2571
  null,
2345
2572
  h(DropZone, { onFile: runDrop, busy, dropRef: lastDrop, phase }),
2346
2573
 
2347
- /* 从网络安装:GitHub / npm / 直链。
2348
- * 下载后服务端会校验它真的是整合包(inspectBundle),
2349
- * 不是就明确报「下载到的不是整合包」,不会硬导进去。 */
2350
- h(
2351
- 'div',
2352
- { className: 'pp-card', style: { marginTop: 14 } },
2353
- h('h3', { style: { margin: '0 0 4px', fontSize: 14, fontWeight: 600 } }, t('net.title')),
2354
- h('p', { className: 'pp-hint', style: { margin: '0 0 10px' } }, t('net.desc')),
2355
- h(
2356
- 'div',
2357
- { style: { display: 'flex', gap: 8, alignItems: 'flex-start', flexWrap: 'wrap' } },
2358
- h('input', {
2359
- className: 'pp-input pp-mono',
2360
- type: 'text',
2361
- value: netSource,
2362
- placeholder: t('net.placeholder'),
2363
- disabled: busy,
2364
- onInput: (event) => setNetSource(event.target.value),
2365
- onKeyDown: (event) => {
2366
- if (event.key === 'Enter' && !busy) runNetworkInstall();
2367
- },
2368
- style: { flex: '1 1 260px', minWidth: 0, fontSize: 12 },
2369
- }),
2370
- h(
2371
- 'button',
2372
- {
2373
- className: 'pp-btn',
2374
- disabled: busy || !netSource.trim(),
2375
- onClick: runNetworkInstall,
2376
- },
2377
- busy ? t('net.running') : t('net.go'),
2378
- ),
2379
- ),
2380
- // 结果:下载成功 / 不是整合包 / 其它错误
2381
- netResult?.error
2382
- ? h(
2383
- 'div',
2384
- { style: { marginTop: 10 } },
2385
- ['NOT_A_BUNDLE', 'NOT_A_ZIP', 'BAD_FORMAT', 'BAD_MANIFEST', 'BAD_PACK'].includes(String(netResult.code ?? '')) ||
2386
- /不是整合包|没有 manifest/i.test(String(netResult.error))
2387
- ? h(
2388
- 'div',
2389
- { className: 'pp-not-bundle' },
2390
- h('div', { className: 'pp-not-bundle-title' }, t('net.notBundle')),
2391
- h('div', { className: 'pp-not-bundle-detail' }, String(netResult.error)),
2392
- )
2393
- : h(Alert, { kind: 'err' }, netResult.error),
2394
- )
2395
- : netResult?.ok
2396
- ? h(
2397
- 'div',
2398
- { className: 'pp-hint', style: { marginTop: 8 } },
2399
- `✓ ${netResult.from} · ${netResult.name ?? ''} · ${
2400
- netResult.bytes ? (netResult.bytes / 1048576).toFixed(1) + ' MiB' : ''
2401
- } · ${netResult.plugins?.length ?? 0} ${t('plugins')}`,
2402
- )
2403
- : null,
2404
- ),
2405
-
2406
2574
  // 后台任务:切走画面回来能看到刚才那次导入的结果
2407
2575
  h(JobList, { jobs, onClear: clearJobHistory, t }),
2408
2576
 
@@ -2693,6 +2861,19 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
2693
2861
  setOut(looksLikeFile || picked.endsWith('\\') || picked.endsWith('/') ? picked : `${picked}\\`);
2694
2862
  },
2695
2863
  }),
2864
+ /* 「添加整合包」弹窗:带来源输入 + 校验提示 + 整宽安装按钮,
2865
+ * 布局对齐 DSH 自带的「添加插件」弹窗。 */
2866
+ h(AddBundleDialog, {
2867
+ open: netOpen,
2868
+ value: netSource,
2869
+ onChange: setNetSource,
2870
+ result: netResult,
2871
+ busy,
2872
+ phase,
2873
+ onInstall: runNetworkInstall,
2874
+ onClose: () => setNetOpen(false),
2875
+ t,
2876
+ }),
2696
2877
  // 重名冲突弹窗:叠在最上层
2697
2878
  h(ConflictDialog, {
2698
2879
  pending: pendingImport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-pack",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "DeepSeek Harness 插件整合包:一键把当前 profile 的第三方插件连依赖和配置导出成 zip(内部每个插件是标准 npm tgz),换机/换 profile 拖进去就能还原。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",