dsh-plugin 0.1.0

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/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "dsh-plugin",
3
+ "version": "0.1.0",
4
+ "description": "A community plugin marketplace for DeepSeek Harness, built to the official plugin spec — browse, search and install 4000+ human-curated community plugins without leaving the app. · DeepSeek Harness 社区插件市场(遵循官方开发规范):4000+ 人工精选社区插件,每日更新。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/dshplugin/dsh-plugin-hub.git"
12
+ },
13
+ "homepage": "https://dsh-plugin.org",
14
+ "keywords": [
15
+ "deepseek",
16
+ "deepseek-harness",
17
+ "harness",
18
+ "dsh",
19
+ "dsh-plugin",
20
+ "plugin-marketplace",
21
+ "plugin-hub",
22
+ "community-plugins",
23
+ "plugins",
24
+ "marketplace",
25
+ "ai",
26
+ "agent",
27
+ "cli",
28
+ "typescript",
29
+ "open-source"
30
+ ],
31
+ "scripts": {
32
+ "build": "npm run build:client",
33
+ "build:client": "tsdown && node scripts/normalize-client-banner.mjs",
34
+ "readme:stats": "node scripts/sync-readme-stats.mjs",
35
+ "typecheck": "tsc -p tsconfig.client.json --noEmit",
36
+ "check": "npm run typecheck && npm run build",
37
+ "prepack": "npm run build"
38
+ },
39
+ "dependencies": {},
40
+ "peerDependencies": {
41
+ "@deepseek-ai/cordis": "4.0.1"
42
+ },
43
+ "dsh": {
44
+ "bundle": {
45
+ "patch": "./cordis.patch.yml"
46
+ },
47
+ "client": {
48
+ "inject": [
49
+ "@deepseek-ai/dsh-client-locale",
50
+ "@deepseek-ai/dsh-client-ui-slots"
51
+ ],
52
+ "platform": "web"
53
+ }
54
+ },
55
+ "exports": {
56
+ ".": {
57
+ "types": "./lib/types/index.d.ts",
58
+ "default": "./lib/index.js"
59
+ },
60
+ "./client": "./client/client.js",
61
+ "./cordis.patch.yml": "./cordis.patch.yml",
62
+ "./package.json": "./package.json"
63
+ },
64
+ "files": [
65
+ "lib",
66
+ "src",
67
+ "client",
68
+ "cordis.patch.yml",
69
+ "LICENSE"
70
+ ],
71
+ "devDependencies": {
72
+ "@types/node": "24.13.3",
73
+ "@types/react": "18.3.31",
74
+ "lightningcss": "1.33.0",
75
+ "react": "18.3.1",
76
+ "tsdown": "0.22.14",
77
+ "typescript": "7.0.2"
78
+ },
79
+ "peerDependenciesMeta": {
80
+ "@deepseek-ai/cordis": {
81
+ "optional": true
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,569 @@
1
+ /* DSH-Plugin Hub section styles. Colors resolve through the host's
2
+ * --dsw-alias-* design tokens with the original light-mode literal as
3
+ * fallback, so the section follows the active theme. */
4
+ .root {
5
+ height: 100%;
6
+ min-width: 0;
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 8px;
10
+ color: var(--dsw-alias-label-primary, #1f2328);
11
+ }
12
+
13
+ /* —— header —— */
14
+
15
+ .header {
16
+ display: flex;
17
+ align-items: center;
18
+ justify-content: space-between;
19
+ gap: 12px;
20
+ flex-wrap: wrap;
21
+ padding: 2px 2px 0;
22
+ }
23
+
24
+ .brand {
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 10px;
28
+ min-width: 0;
29
+ }
30
+
31
+ .brandText {
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 1px;
35
+ min-width: 0;
36
+ }
37
+
38
+ .title {
39
+ font-size: 14px;
40
+ line-height: 20px;
41
+ font-weight: 600;
42
+ margin: 0;
43
+ }
44
+
45
+ .tagline {
46
+ font-size: 12px;
47
+ line-height: 18px;
48
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
49
+ margin: 0;
50
+ display: -webkit-box;
51
+ -webkit-line-clamp: 2;
52
+ -webkit-box-orient: vertical;
53
+ overflow: hidden;
54
+ }
55
+
56
+ .controls {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 8px;
60
+ flex-shrink: 0;
61
+ }
62
+
63
+ /* —— ad banner —— */
64
+
65
+ /* 广告条:固定蓝紫渐变 + 白字,不随主题变量漂移,两种主题下都醒目。
66
+ 与 toast 相同思路:固定颜色保证可读性。 */
67
+ .adBanner {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 8px;
71
+ padding: 7px 12px;
72
+ border: 1px solid rgba(139, 92, 246, 0.55);
73
+ border-radius: 8px;
74
+ background: linear-gradient(90deg, #4f46e5 0%, #7c3aed 100%);
75
+ color: #ffffff;
76
+ text-decoration: none;
77
+ cursor: pointer;
78
+ box-shadow: 0 2px 10px rgba(79, 70, 229, 0.28);
79
+ transition: filter 0.15s ease, box-shadow 0.15s ease;
80
+ }
81
+
82
+ .adBanner:hover {
83
+ filter: brightness(1.1);
84
+ box-shadow: 0 4px 16px rgba(124, 58, 237, 0.42);
85
+ }
86
+
87
+ .adBadge {
88
+ flex-shrink: 0;
89
+ font-size: 10px;
90
+ font-weight: 700;
91
+ letter-spacing: 0.04em;
92
+ line-height: 1;
93
+ color: #ffffff;
94
+ background: rgba(255, 255, 255, 0.16);
95
+ border: 1px solid rgba(255, 255, 255, 0.55);
96
+ border-radius: 4px;
97
+ padding: 3px 6px;
98
+ white-space: nowrap;
99
+ }
100
+
101
+ .adText {
102
+ min-width: 0;
103
+ overflow: hidden;
104
+ text-overflow: ellipsis;
105
+ white-space: nowrap;
106
+ font-size: 12px;
107
+ line-height: 18px;
108
+ color: #ffffff;
109
+ }
110
+
111
+ .adArrow {
112
+ flex-shrink: 0;
113
+ margin-left: auto;
114
+ font-size: 13px;
115
+ color: #ffffff;
116
+ }
117
+
118
+ .search {
119
+ width: 190px;
120
+ font-size: 12px;
121
+ line-height: 18px;
122
+ color: inherit;
123
+ background: transparent;
124
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
125
+ border-radius: 6px;
126
+ padding: 4px 9px;
127
+ outline: none;
128
+ transition: border-color 120ms ease;
129
+ }
130
+
131
+ .search::placeholder {
132
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
133
+ }
134
+
135
+ .search:focus {
136
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
137
+ }
138
+
139
+ .sort {
140
+ font-size: 12px;
141
+ line-height: 18px;
142
+ color: var(--dsw-alias-label-secondary, #6b7280);
143
+ background: transparent;
144
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
145
+ border-radius: 6px;
146
+ padding: 4px 8px;
147
+ outline: none;
148
+ cursor: pointer;
149
+ }
150
+
151
+ .sort:hover {
152
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
153
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
154
+ }
155
+
156
+ .langBtn {
157
+ flex-shrink: 0;
158
+ font-size: 12px;
159
+ line-height: 18px;
160
+ color: var(--dsw-alias-label-secondary, #6b7280);
161
+ background: transparent;
162
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
163
+ border-radius: 6px;
164
+ padding: 4px 9px;
165
+ cursor: pointer;
166
+ transition: color 120ms ease, border-color 120ms ease;
167
+ }
168
+
169
+ .langBtn:hover {
170
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
171
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
172
+ }
173
+
174
+ .openBtn {
175
+ flex-shrink: 0;
176
+ display: inline-flex;
177
+ align-items: center;
178
+ gap: 4px;
179
+ font-size: 12px;
180
+ font-weight: 500;
181
+ line-height: 20px;
182
+ color: var(--dsw-alias-label-secondary, #6b7280);
183
+ text-decoration: none;
184
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
185
+ border-radius: 6px;
186
+ padding: 3px 9px;
187
+ background: transparent;
188
+ cursor: pointer;
189
+ white-space: nowrap;
190
+ transition: color 120ms ease, border-color 120ms ease;
191
+ }
192
+
193
+ .openBtn:hover {
194
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
195
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
196
+ }
197
+
198
+ .openArrow {
199
+ font-size: 12px;
200
+ line-height: 1;
201
+ }
202
+
203
+ /* —— category chips —— */
204
+
205
+ .tabs {
206
+ display: flex;
207
+ align-items: center;
208
+ flex-wrap: wrap;
209
+ gap: 6px;
210
+ padding: 2px 2px 8px;
211
+ border-bottom: 1px solid var(--dsw-alias-border-l1, #eceef1);
212
+ }
213
+
214
+ .tab,
215
+ .tabActive {
216
+ display: inline-flex;
217
+ align-items: center;
218
+ gap: 6px;
219
+ flex-shrink: 0;
220
+ font-size: 12px;
221
+ line-height: 18px;
222
+ border: 1px solid transparent;
223
+ border-radius: 999px;
224
+ padding: 3px 10px;
225
+ cursor: pointer;
226
+ transition: color 120ms ease, background 120ms ease, border-color 120ms ease;
227
+ }
228
+
229
+ .tab {
230
+ color: var(--dsw-alias-label-secondary, #6b7280);
231
+ background: transparent;
232
+ border-color: var(--dsw-alias-border-l2, #e5e7eb);
233
+ }
234
+
235
+ .tab:hover {
236
+ color: var(--dsw-alias-label-primary, #1f2328);
237
+ background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.08));
238
+ border-color: var(--dsw-alias-border-l1, #eceef1);
239
+ }
240
+
241
+ .tabActive {
242
+ color: #fff;
243
+ background: var(--dsw-alias-brand-primary, #4f6ef7);
244
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
245
+ }
246
+
247
+ .tabCount,
248
+ .tabCountActive {
249
+ font-size: 10px;
250
+ line-height: 14px;
251
+ border-radius: 999px;
252
+ padding: 0 5px;
253
+ min-width: 16px;
254
+ text-align: center;
255
+ }
256
+
257
+ .tabCount {
258
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
259
+ background: var(--dsw-alias-bg-layer-2, rgba(128, 128, 128, 0.1));
260
+ }
261
+
262
+ .tabActive .tabCountActive {
263
+ color: #fff;
264
+ background: rgba(255, 255, 255, 0.22);
265
+ }
266
+
267
+ /* —— body / list —— */
268
+
269
+ .body {
270
+ flex: 1;
271
+ min-height: 0;
272
+ display: flex;
273
+ flex-direction: column;
274
+ }
275
+
276
+ .list {
277
+ flex: 1;
278
+ min-height: 0;
279
+ overflow-y: auto;
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 6px;
283
+ padding: 2px 4px 4px 2px;
284
+ }
285
+
286
+ .card {
287
+ display: flex;
288
+ align-items: stretch;
289
+ justify-content: space-between;
290
+ gap: 12px;
291
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
292
+ border-radius: 8px;
293
+ padding: 9px 12px;
294
+ background: var(--dsw-alias-bg-layer-1, rgba(128, 128, 128, 0.06));
295
+ transition: border-color 120ms ease, background 120ms ease;
296
+ }
297
+
298
+ .card:hover {
299
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
300
+ background: var(--dsw-alias-bg-layer-2, rgba(128, 128, 128, 0.1));
301
+ }
302
+
303
+ .cardMain {
304
+ min-width: 0;
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: 4px;
308
+ }
309
+
310
+ .cardHead {
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 6px;
314
+ min-width: 0;
315
+ }
316
+
317
+ .cardTitle {
318
+ font-size: 13px;
319
+ line-height: 18px;
320
+ font-weight: 600;
321
+ white-space: nowrap;
322
+ overflow: hidden;
323
+ text-overflow: ellipsis;
324
+ }
325
+
326
+ .categoryBadge,
327
+ .verified {
328
+ flex-shrink: 0;
329
+ font-size: 10px;
330
+ line-height: 16px;
331
+ border-radius: 4px;
332
+ padding: 0 6px;
333
+ border: 1px solid transparent;
334
+ }
335
+
336
+ .categoryBadge {
337
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
338
+ border-color: var(--dsw-alias-button-ghost-active-border, rgba(79, 110, 247, 0.25));
339
+ }
340
+
341
+ .verified {
342
+ color: var(--dsw-alias-state-success-primary, #1a7f37);
343
+ border-color: var(--dsw-alias-state-success-secondary, rgba(26, 127, 55, 0.3));
344
+ }
345
+
346
+ .desc {
347
+ font-size: 12px;
348
+ line-height: 18px;
349
+ color: var(--dsw-alias-label-secondary, #6b7280);
350
+ margin: 0;
351
+ display: -webkit-box;
352
+ -webkit-line-clamp: 2;
353
+ -webkit-box-orient: vertical;
354
+ overflow: hidden;
355
+ }
356
+
357
+ .topics {
358
+ display: flex;
359
+ align-items: center;
360
+ gap: 4px;
361
+ flex-wrap: wrap;
362
+ min-width: 0;
363
+ }
364
+
365
+ .topic {
366
+ flex-shrink: 0;
367
+ font-size: 10px;
368
+ line-height: 16px;
369
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
370
+ background: var(--dsw-alias-bg-layer-2, rgba(128, 128, 128, 0.1));
371
+ border-radius: 4px;
372
+ padding: 0 6px;
373
+ white-space: nowrap;
374
+ }
375
+
376
+ .cardSide {
377
+ flex-shrink: 0;
378
+ display: flex;
379
+ flex-direction: column;
380
+ align-items: flex-end;
381
+ justify-content: space-between;
382
+ gap: 6px;
383
+ }
384
+
385
+ .stats {
386
+ display: flex;
387
+ flex-direction: column;
388
+ align-items: flex-end;
389
+ gap: 1px;
390
+ }
391
+
392
+ .star {
393
+ font-size: 11px;
394
+ line-height: 16px;
395
+ color: var(--dsw-alias-state-warn-primary, #b8860b);
396
+ white-space: nowrap;
397
+ }
398
+
399
+ .fork {
400
+ font-size: 11px;
401
+ line-height: 16px;
402
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
403
+ white-space: nowrap;
404
+ }
405
+
406
+ .date {
407
+ font-size: 10px;
408
+ line-height: 14px;
409
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
410
+ white-space: nowrap;
411
+ }
412
+
413
+ .installBtn,
414
+ .installBtnCopied,
415
+ .detailBtn {
416
+ font-size: 11px;
417
+ line-height: 18px;
418
+ border-radius: 6px;
419
+ padding: 2px 10px;
420
+ cursor: pointer;
421
+ transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
422
+ }
423
+
424
+ .installBtn {
425
+ color: var(--dsw-alias-label-secondary, #6b7280);
426
+ background: transparent;
427
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
428
+ }
429
+
430
+ .installBtn:hover {
431
+ color: #4f6ef7;
432
+ border-color: #4f6ef7;
433
+ }
434
+
435
+ /* Primary action: opens the plugin detail page on dsh-plugin.org.
436
+ Fixed colors (not host tokens) so it stays readable in dark themes. */
437
+ .detailBtn {
438
+ color: #4f6ef7;
439
+ background: transparent;
440
+ border: 1px solid #4f6ef7;
441
+ text-decoration: none;
442
+ display: inline-flex;
443
+ align-items: center;
444
+ font-weight: 500;
445
+ }
446
+
447
+ .detailBtn:hover {
448
+ color: #ffffff;
449
+ background: #4f6ef7;
450
+ }
451
+
452
+ .actions {
453
+ display: flex;
454
+ align-items: center;
455
+ gap: 6px;
456
+ }
457
+
458
+ .installBtnCopied {
459
+ color: #ffffff;
460
+ background: #4f6ef7;
461
+ border: 1px solid #4f6ef7;
462
+ }
463
+
464
+ /* 复制成功提示条:窗口正中央浮出,纯黑色文字条,无遮罩无图标。
465
+ base 上直接写死居中 transform,动画结束(fill-mode 默认 none)后
466
+ transform 会回落到 base 值,保证动画前后位置一致、不跳动。 */
467
+ .toast {
468
+ position: fixed;
469
+ left: 50%;
470
+ top: 50%;
471
+ transform: translate(-50%, -50%);
472
+ z-index: 1000;
473
+ padding: 10px 16px;
474
+ border-radius: 8px;
475
+ background: #111827;
476
+ border: 1px solid rgba(255, 255, 255, 0.1);
477
+ color: #f9fafb;
478
+ font-size: 12px;
479
+ line-height: 18px;
480
+ box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
481
+ animation: toastIn 220ms ease-out;
482
+ pointer-events: none;
483
+ white-space: nowrap;
484
+ }
485
+
486
+ @keyframes toastIn {
487
+ from {
488
+ opacity: 0;
489
+ transform: translate(-50%, -44%);
490
+ }
491
+ to {
492
+ opacity: 1;
493
+ transform: translate(-50%, -50%);
494
+ }
495
+ }
496
+
497
+ /* —— states —— */
498
+
499
+ .state {
500
+ flex: 1;
501
+ min-height: 160px;
502
+ display: flex;
503
+ flex-direction: column;
504
+ align-items: center;
505
+ justify-content: center;
506
+ gap: 8px;
507
+ padding: 24px;
508
+ text-align: center;
509
+ font-size: 12px;
510
+ line-height: 18px;
511
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
512
+ }
513
+
514
+ .stateTitle {
515
+ font-size: 13px;
516
+ font-weight: 600;
517
+ color: var(--dsw-alias-label-primary, #1f2328);
518
+ }
519
+
520
+ .stateDesc {
521
+ max-width: 420px;
522
+ }
523
+
524
+ .retryBtn {
525
+ margin-top: 4px;
526
+ font-size: 12px;
527
+ line-height: 18px;
528
+ color: var(--dsw-alias-label-secondary, #6b7280);
529
+ border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
530
+ border-radius: 6px;
531
+ padding: 4px 12px;
532
+ background: transparent;
533
+ cursor: pointer;
534
+ }
535
+
536
+ .retryBtn:hover {
537
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
538
+ border-color: var(--dsw-alias-brand-primary, #4f6ef7);
539
+ }
540
+
541
+ /* —— footer —— */
542
+
543
+ .footer {
544
+ flex-shrink: 0;
545
+ display: flex;
546
+ align-items: center;
547
+ justify-content: space-between;
548
+ gap: 8px;
549
+ padding: 6px 4px 0;
550
+ border-top: 1px solid var(--dsw-alias-border-l1, #eceef1);
551
+ }
552
+
553
+ .footText {
554
+ font-size: 11px;
555
+ line-height: 16px;
556
+ color: var(--dsw-alias-label-tertiary, #8b93a1);
557
+ }
558
+
559
+ .footLink {
560
+ font-size: 11px;
561
+ line-height: 16px;
562
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
563
+ text-decoration: none;
564
+ white-space: nowrap;
565
+ }
566
+
567
+ .footLink:hover {
568
+ text-decoration: underline;
569
+ }
@@ -0,0 +1,5 @@
1
+ /** Type declaration for CSS Modules consumed by the browser client. */
2
+ declare module '*.module.css' {
3
+ const classes: Record<string, string>
4
+ export default classes
5
+ }