dsh-plugin-pack 1.0.6 → 1.0.7

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 +258 -67
  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
 
@@ -2342,67 +2550,37 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
2342
2550
  const importPage = h(
2343
2551
  'div',
2344
2552
  null,
2345
- h(DropZone, { onFile: runDrop, busy, dropRef: lastDrop, phase }),
2346
-
2347
- /* 从网络安装:GitHub / npm / 直链。
2348
- * 下载后服务端会校验它真的是整合包(inspectBundle),
2349
- * 不是就明确报「下载到的不是整合包」,不会硬导进去。 */
2553
+ /* 右上角「添加整合包」按钮 —— 和 DSH 自带的「添加插件」同位置同风格。
2554
+ * 点开是一个弹窗,在里面填地址、点安装。 */
2350
2555
  h(
2351
2556
  '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')),
2557
+ {
2558
+ style: {
2559
+ display: 'flex',
2560
+ alignItems: 'center',
2561
+ justifyContent: 'space-between',
2562
+ gap: 12,
2563
+ marginBottom: 12,
2564
+ },
2565
+ },
2566
+ h('div', { style: { fontSize: 14, fontWeight: 600 } }, t('import.pageTitle')),
2355
2567
  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,
2568
+ 'button',
2569
+ {
2570
+ className: 'pp-btn',
2571
+ style: { display: 'inline-flex', alignItems: 'center', gap: 6, flex: 'none' },
2572
+ onClick: () => {
2573
+ setNetResult(null);
2574
+ setNetOpen(true);
2376
2575
  },
2377
- busy ? t('net.running') : t('net.go'),
2378
- ),
2576
+ },
2577
+ h('span', { style: { fontSize: 15, lineHeight: 1 } }, '+'),
2578
+ t('net.button'),
2379
2579
  ),
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
2580
  ),
2405
2581
 
2582
+ h(DropZone, { onFile: runDrop, busy, dropRef: lastDrop, phase }),
2583
+
2406
2584
  // 后台任务:切走画面回来能看到刚才那次导入的结果
2407
2585
  h(JobList, { jobs, onClear: clearJobHistory, t }),
2408
2586
 
@@ -2693,6 +2871,19 @@ window.__ModuleLoader__.load({ id: 'dsh-plugin-pack', factory: (require) => {
2693
2871
  setOut(looksLikeFile || picked.endsWith('\\') || picked.endsWith('/') ? picked : `${picked}\\`);
2694
2872
  },
2695
2873
  }),
2874
+ /* 「添加整合包」弹窗:带来源输入 + 校验提示 + 整宽安装按钮,
2875
+ * 布局对齐 DSH 自带的「添加插件」弹窗。 */
2876
+ h(AddBundleDialog, {
2877
+ open: netOpen,
2878
+ value: netSource,
2879
+ onChange: setNetSource,
2880
+ result: netResult,
2881
+ busy,
2882
+ phase,
2883
+ onInstall: runNetworkInstall,
2884
+ onClose: () => setNetOpen(false),
2885
+ t,
2886
+ }),
2696
2887
  // 重名冲突弹窗:叠在最上层
2697
2888
  h(ConflictDialog, {
2698
2889
  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.7",
4
4
  "description": "DeepSeek Harness 插件整合包:一键把当前 profile 的第三方插件连依赖和配置导出成 zip(内部每个插件是标准 npm tgz),换机/换 profile 拖进去就能还原。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",