@stolyarovmn/dsh-ui-registry-aggregator 0.4.13 → 0.4.15

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Stolyarovmn
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stolyarovmn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,225 +1,226 @@
1
- # Registry Aggregator for DeepSeek Harness
2
-
3
- Registry Aggregator is a federated plugin-discovery UI for DeepSeek Harness. It combines trusted plugin registries, GitHub repositories, and compatible JSON catalogs into one normalized index while leaving installation and plugin lifecycle management to the native DSH Plugin Manager.
4
-
5
- ## Screenshots
6
-
7
- ### Connected sources
8
-
9
- Built-in npm and GitHub sources are health-checked, counted, and managed from the **Sources** view.
10
-
11
- ![Registry Aggregator — connected sources](docs/screenshots/registry-sources.webp)
12
-
13
- ### Browse and search
14
-
15
- Search across connected sources, filter results, inspect evidence, and install a verified DSH bundle without leaving DeepSeek Harness.
16
-
17
- ![Registry Aggregator — Browse search](docs/screenshots/registry-browse.webp)
18
-
19
- ## Highlights
20
-
21
- - **Federated Sources** — combine npm, GitHub, and compatible JSON catalogs.
22
- - **Browse** — search all enabled sources as one deduplicated index.
23
- - **Verified DSH bundles** — npm/GitHub candidates are checked for a root `dsh.bundle.patch` before they are exposed as installable results.
24
- - **Evidence** — display release channel, GitHub stars, npm 30-day downloads, freshness, source metadata, and declared DSH compatibility when available.
25
- - **Filters** — stable releases, age, category, and DSH metadata.
26
- - **Multi-sort** — compose Stars, Downloads, Freshness, and Name; each criterion can be ascending or descending.
27
- - **Pagination** — 20, 50, or 100 items per page with navigation above and below results.
28
- - **Native install** — one-click installation through the DSH Plugin Manager Host API.
29
- - **Fallback command** — installable results also expose their `dsh plugin add …` command.
30
- - **Responsive popularity metadata** — missing GitHub star counts are hydrated after Browse renders, so GitHub metadata cannot block the initial search result.
31
-
32
- ## What's new in 0.4.13
33
-
34
- 0.4.13 restores the fast, stable Browse/discovery path from the last known-good search implementation and separates GitHub popularity metadata from the critical search path.
35
-
36
- - restored npm/GitHub source discovery and source counters;
37
- - restored fast empty-query and keyword Browse behavior;
38
- - kept exact and partial package-name discovery, including scoped npm packages;
39
- - preserved bundle verification before exposing install actions;
40
- - moved missing GitHub star resolution to a separate asynchronous request after cards render;
41
- - star lookups are cached, best-effort, and limited to the visible page;
42
- - a GitHub statistics failure no longer delays or fails Browse.
43
-
44
- ## Architecture
45
-
46
- ```text
47
- Plugins → Installed → @stolyarovmn/dsh-ui-registry-aggregator
48
- ├─ Sources / Browse UI
49
- ├─ ctx.configForms → source configuration
50
- ├─ authenticated Connection RPC (/api/plugin-sources/*)
51
- │ └─ Host adapters
52
- │ └─ normalize → deduplicate → verify → filter → sort → paginate
53
- └─ ctx.remote.pluginManager
54
- ├─ inspect(spec)
55
- └─ installBundle(spec)
56
- ```
57
-
58
- The browser does not fetch arbitrary catalog URLs directly. External source access happens on the Host side through the authenticated DSH Connection RPC boundary.
59
-
60
- GitHub star enrichment is intentionally separate from the Browse critical path:
61
-
62
- ```text
63
- Browse request
64
- → discover / verify / filter / sort / paginate
65
- → render cards
66
- → request missing GitHub stars for visible repositories
67
- → update cards in place
68
- ```
69
-
70
- ## Install
71
-
72
- ### npm
73
-
74
- After the package is published:
75
-
76
- ```sh
77
- dsh plugin --profile web add @stolyarovmn/dsh-ui-registry-aggregator
78
- ```
79
-
80
- If you run DSH through `pnpm dlx`:
81
-
82
- ```sh
83
- pnpm dlx @deepseek-ai/dsh@0.1.7-rc.1 plugin --profile web add @stolyarovmn/dsh-ui-registry-aggregator
84
- ```
85
-
86
- ### GitHub
87
-
88
- ```sh
89
- pnpm dlx @deepseek-ai/dsh@0.1.7-rc.1 plugin --profile web add "git+https://github.com/Stolyarovmn/dsh-ui-registry-aggregator.git"
90
- ```
91
-
92
- Enable the installed bundle, then open:
93
-
94
- ```text
95
- Plugins → Installed → @stolyarovmn/dsh-ui-registry-aggregator
96
- ```
97
-
98
- npm and GitHub sources are added automatically on first use.
99
-
100
- ## Source types
101
-
102
- | Type | Behavior |
103
- | --- | --- |
104
- | `npm` | npm registry discovery using DSH-related package metadata and keywords. |
105
- | `github` | GitHub repository discovery using DeepSeek-Harness-specific topic intersections. |
106
- | `dsh-plugin-shop` | JSON catalog adapter for a compatible source endpoint. |
107
- | `dshplugin-app` | JSON catalog adapter for a dshplugin.app-compatible endpoint. |
108
- | `custom-json` | Public JSON catalog. |
109
- | `corporate` | JSON catalog with Host-controlled private-network and credential permissions. |
110
-
111
- A JSON source may return a bare array or an object containing `plugins`, `items`, or `results`.
112
-
113
- Example:
114
-
115
- ```json
116
- {
117
- "plugins": [
118
- {
119
- "id": "pdf-tools",
120
- "name": "PDF Tools",
121
- "description": "Extract and merge PDF documents.",
122
- "version": "1.2.0",
123
- "package": "@example/dsh-plugin-pdf",
124
- "repository": "https://github.com/example/dsh-plugin-pdf",
125
- "install": {
126
- "type": "npm",
127
- "spec": "@example/dsh-plugin-pdf@1.2.0"
128
- }
129
- }
130
- ]
131
- }
132
- ```
133
-
134
- Identity precedence is npm package, canonical repository URL, then source-specific id. Duplicate records preserve source attribution, versions, and normalized category tags.
135
-
136
- ## Discovery quality
137
-
138
- Registry Aggregator treats registry search hits as **candidates**, not automatically as installable DSH plugins.
139
-
140
- - npm candidates are verified against their published package metadata.
141
- - Exact npm package names can be resolved from the registry packument instead of relying only on the eventually-consistent search index.
142
- - Short and partial queries combine cached discovery with query-specific npm/GitHub discovery.
143
- - GitHub discovery uses DeepSeek-Harness-specific topic intersections instead of the broad `dsh-plugin` topic alone.
144
- - npm/GitHub candidates must declare a root `dsh.bundle.patch` before the UI exposes **Install** or the fallback command.
145
- - Candidates that are not valid DSH bundles are removed before totals, sorting, pagination, and rendering.
146
- - npm/GitHub source counters represent verified installable bundle candidates rather than raw keyword/topic cardinality.
147
-
148
- ## Popularity evidence
149
-
150
- - npm download counts come from npm package/download metadata.
151
- - GitHub stars are taken from GitHub discovery when the result already contains them.
152
- - If a visible npm-discovered plugin has a GitHub repository but no star count, the client requests the missing repository statistics **after the Browse result is rendered**.
153
- - Async star lookup is cached and limited to visible results; failures are ignored rather than failing Browse.
154
-
155
- ## Sorting
156
-
157
- Sorting criteria are independent and composable:
158
-
159
- - **Stars**
160
- - **Downloads**
161
- - **Freshness**
162
- - **Name**
163
-
164
- Clicking a criterion cycles:
165
-
166
- ```text
167
- off → descending → ascending → off
168
- ```
169
-
170
- The order in which criteria are enabled defines priority.
171
-
172
- ## Compatibility
173
-
174
- - DSH: `>=0.1.7-rc.1 <0.2.0`
175
- - Tested with DSH `0.1.7-rc.1`
176
-
177
- Exact package compatibility is read from package metadata when a publisher declares it. Installation is validated again by the native DSH Plugin Manager.
178
-
179
- ## Security
180
-
181
- Browser-editable source settings never contain credentials.
182
-
183
- Host protections include:
184
-
185
- - HTTP(S)-only source URLs;
186
- - rejection of URL-embedded credentials;
187
- - blocking of loopback, link-local, private, multicast, reserved, and other non-global-unicast destinations by default;
188
- - DNS pinning and redirect destination revalidation;
189
- - source, response-size, result-count, concurrency, and RPC-size limits;
190
- - Host-controlled allowlists for private sources and environment-based bearer tokens;
191
- - install-spec validation before a command is exposed or sent to the Plugin Manager.
192
-
193
- The Install action executes third-party code through the native DSH Plugin Manager. Review the source and package before installation.
194
-
195
- ## Host configuration
196
-
197
- ```yaml
198
- - id: registry-aggregator
199
- name: '@stolyarovmn/dsh-ui-registry-aggregator'
200
- config:
201
- timeoutMs: 10000
202
- maxResponseBytes: 2097152
203
- maxPlugins: 2000
204
- maxSources: 20
205
- maxTotalPlugins: 5000
206
- maxRpcBytes: 4194304
207
- concurrency: 4
208
- privateSourceIds:
209
- - corporate
210
- auth:
211
- - sourceId: corporate
212
- tokenEnv: DSH_CORPORATE_REGISTRY_TOKEN
213
- ```
214
-
215
- ## Development
216
-
217
- ```sh
218
- npm install
219
- npm test
220
- npm run test:pack
221
- ```
222
-
223
- ## License
224
-
225
- MIT
1
+ # Registry Aggregator for DeepSeek Harness
2
+
3
+ Registry Aggregator is a federated plugin-discovery UI for DeepSeek Harness. It combines trusted plugin registries, GitHub repositories, and compatible JSON catalogs into one normalized index while leaving installation and plugin lifecycle management to the native DSH Plugin Manager.
4
+
5
+ ## Screenshots
6
+
7
+ ### Connected sources
8
+
9
+ Built-in npm and GitHub sources are health-checked, counted, and managed from the **Sources** view.
10
+
11
+ ![Registry Aggregator — connected sources](docs/screenshots/registry-sources.webp)
12
+
13
+ ### Browse and search
14
+
15
+ Search across connected sources, filter results, inspect evidence, and install a verified DSH bundle without leaving DeepSeek Harness.
16
+
17
+ ![Registry Aggregator — Browse search](docs/screenshots/registry-browse.webp)
18
+
19
+ ## Highlights
20
+
21
+ - **Federated Sources** — combine npm, GitHub, and compatible JSON catalogs.
22
+ - **Browse** — search all enabled sources as one deduplicated index.
23
+ - **Verified DSH bundles** — npm/GitHub candidates are checked for a root `dsh.bundle.patch` before they are exposed as installable results.
24
+ - **Evidence** — display release channel, GitHub stars, npm 30-day downloads, freshness, source metadata, and declared DSH compatibility when available.
25
+ - **Filters** — stable releases, age, category, and DSH metadata.
26
+ - **Multi-sort** — compose Stars, Downloads, Freshness, and Name; each criterion can be ascending or descending.
27
+ - **Pagination** — 20, 50, or 100 items per page with navigation above and below results.
28
+ - **Native install** — one-click installation through the DSH Plugin Manager Host API.
29
+ - **Fallback command** — installable results also expose their `dsh plugin add …` command.
30
+ - **Responsive popularity metadata** — missing GitHub star counts are hydrated after Browse renders, so GitHub metadata cannot block the initial search result.
31
+
32
+ ## What's new in 0.4.15
33
+
34
+ 0.4.15 focuses on reliability and native DSH integration while preserving the existing Browse evidence path.
35
+
36
+ - lightweight source health checks are separated from verified DSH bundle counts;
37
+ - npm and GitHub counts load independently with native DSH progress indicators;
38
+ - GitHub requests retry transient failures, while health no longer consumes Search API quota;
39
+ - installed bundles are detected through the native Plugin Manager and duplicate installs are disabled;
40
+ - newer discovered versions are shown as advisory `Update available` notices;
41
+ - active installs can be cancelled through the native Plugin Manager request id;
42
+ - npm results can be enriched with exact GitHub provenance without broad GitHub pagination;
43
+ - search relevance is presentation-only, so GitHub stars, downloads, evidence, pagination, and explicit sorting keep their existing behavior.
44
+
45
+ Tested with DSH `0.1.7-rc.2`.
46
+
47
+ ## Architecture
48
+
49
+ ```text
50
+ Plugins → Installed → @stolyarovmn/dsh-ui-registry-aggregator
51
+ ├─ Sources / Browse UI
52
+ ├─ ctx.configForms → source configuration
53
+ ├─ authenticated Connection RPC (/api/plugin-sources/*)
54
+ │ └─ Host adapters
55
+ │ └─ normalize → deduplicate → verify → filter → sort → paginate
56
+ └─ ctx.remote.pluginManager
57
+ ├─ inspect(spec)
58
+ └─ installBundle(spec)
59
+ ```
60
+
61
+ The browser does not fetch arbitrary catalog URLs directly. External source access happens on the Host side through the authenticated DSH Connection RPC boundary.
62
+
63
+ GitHub star enrichment is intentionally separate from the Browse critical path:
64
+
65
+ ```text
66
+ Browse request
67
+ → discover / verify / filter / sort / paginate
68
+ → render cards
69
+ → request missing GitHub stars for visible repositories
70
+ → update cards in place
71
+ ```
72
+
73
+ ## Install
74
+
75
+ ### npm
76
+
77
+ ```sh
78
+ dsh plugin --profile web add @stolyarovmn/dsh-ui-registry-aggregator
79
+ ```
80
+
81
+ If you run DSH through `pnpm dlx`:
82
+
83
+ ```sh
84
+ pnpm dlx @deepseek-ai/dsh@0.1.7-rc.1 plugin --profile web add @stolyarovmn/dsh-ui-registry-aggregator
85
+ ```
86
+
87
+ ### GitHub
88
+
89
+ ```sh
90
+ pnpm dlx @deepseek-ai/dsh@0.1.7-rc.1 plugin --profile web add "git+https://github.com/Stolyarovmn/dsh-ui-registry-aggregator.git"
91
+ ```
92
+
93
+ Enable the installed bundle, then open:
94
+
95
+ ```text
96
+ Plugins → Installed → @stolyarovmn/dsh-ui-registry-aggregator
97
+ ```
98
+
99
+ npm and GitHub sources are added automatically on first use.
100
+
101
+ ## Source types
102
+
103
+ | Type | Behavior |
104
+ | --- | --- |
105
+ | `npm` | npm registry discovery using DSH-related package metadata and keywords. |
106
+ | `github` | GitHub repository discovery using DeepSeek-Harness-specific topic intersections. |
107
+ | `dsh-plugin-shop` | JSON catalog adapter for a compatible source endpoint. |
108
+ | `dshplugin-app` | JSON catalog adapter for a dshplugin.app-compatible endpoint. |
109
+ | `custom-json` | Public JSON catalog. |
110
+ | `corporate` | JSON catalog with Host-controlled private-network and credential permissions. |
111
+
112
+ A JSON source may return a bare array or an object containing `plugins`, `items`, or `results`.
113
+
114
+ Example:
115
+
116
+ ```json
117
+ {
118
+ "plugins": [
119
+ {
120
+ "id": "pdf-tools",
121
+ "name": "PDF Tools",
122
+ "description": "Extract and merge PDF documents.",
123
+ "version": "1.2.0",
124
+ "package": "@example/dsh-plugin-pdf",
125
+ "repository": "https://github.com/example/dsh-plugin-pdf",
126
+ "install": {
127
+ "type": "npm",
128
+ "spec": "@example/dsh-plugin-pdf@1.2.0"
129
+ }
130
+ }
131
+ ]
132
+ }
133
+ ```
134
+
135
+ Identity precedence is npm package, canonical repository URL, then source-specific id. Duplicate records preserve source attribution, versions, and normalized category tags.
136
+
137
+ ## Discovery quality
138
+
139
+ Registry Aggregator treats registry search hits as **candidates**, not automatically as installable DSH plugins.
140
+
141
+ - npm candidates are verified against their published package metadata.
142
+ - Exact npm package names can be resolved from the registry packument instead of relying only on the eventually-consistent search index.
143
+ - Short and partial queries combine cached discovery with query-specific npm/GitHub discovery.
144
+ - GitHub discovery uses DeepSeek-Harness-specific topic intersections instead of the broad `dsh-plugin` topic alone.
145
+ - npm/GitHub candidates must declare a root `dsh.bundle.patch` before the UI exposes **Install** or the fallback command.
146
+ - Candidates that are not valid DSH bundles are removed before totals, sorting, pagination, and rendering.
147
+ - npm/GitHub source counters represent verified installable bundle candidates rather than raw keyword/topic cardinality.
148
+
149
+ ## Popularity evidence
150
+
151
+ - npm download counts come from npm package/download metadata.
152
+ - GitHub stars are taken from GitHub discovery when the result already contains them.
153
+ - If a visible npm-discovered plugin has a GitHub repository but no star count, the client requests the missing repository statistics **after the Browse result is rendered**.
154
+ - Async star lookup is cached and limited to visible results; failures are ignored rather than failing Browse.
155
+
156
+ ## Sorting
157
+
158
+ Sorting criteria are independent and composable:
159
+
160
+ - **Stars**
161
+ - **Downloads**
162
+ - **Freshness**
163
+ - **Name**
164
+
165
+ Clicking a criterion cycles:
166
+
167
+ ```text
168
+ off → descending → ascending → off
169
+ ```
170
+
171
+ The order in which criteria are enabled defines priority.
172
+
173
+ ## Compatibility
174
+
175
+ - DSH: `>=0.1.7-rc.1 <0.2.0`
176
+ - Tested with DSH `0.1.7-rc.2`
177
+
178
+ Exact package compatibility is read from package metadata when a publisher declares it. Installation is validated again by the native DSH Plugin Manager.
179
+
180
+ ## Security
181
+
182
+ Browser-editable source settings never contain credentials.
183
+
184
+ Host protections include:
185
+
186
+ - HTTP(S)-only source URLs;
187
+ - rejection of URL-embedded credentials;
188
+ - blocking of loopback, link-local, private, multicast, reserved, and other non-global-unicast destinations by default;
189
+ - DNS pinning and redirect destination revalidation;
190
+ - source, response-size, result-count, concurrency, and RPC-size limits;
191
+ - Host-controlled allowlists for private sources and environment-based bearer tokens;
192
+ - install-spec validation before a command is exposed or sent to the Plugin Manager.
193
+
194
+ The Install action executes third-party code through the native DSH Plugin Manager. Review the source and package before installation.
195
+
196
+ ## Host configuration
197
+
198
+ ```yaml
199
+ - id: registry-aggregator
200
+ name: '@stolyarovmn/dsh-ui-registry-aggregator'
201
+ config:
202
+ timeoutMs: 10000
203
+ maxResponseBytes: 2097152
204
+ maxPlugins: 2000
205
+ maxSources: 20
206
+ maxTotalPlugins: 5000
207
+ maxRpcBytes: 4194304
208
+ concurrency: 4
209
+ privateSourceIds:
210
+ - corporate
211
+ auth:
212
+ - sourceId: corporate
213
+ tokenEnv: DSH_CORPORATE_REGISTRY_TOKEN
214
+ ```
215
+
216
+ ## Development
217
+
218
+ ```sh
219
+ npm install
220
+ npm test
221
+ npm run test:pack
222
+ ```
223
+
224
+ ## License
225
+
226
+ MIT
package/cordis.patch.yml CHANGED
@@ -1,6 +1,6 @@
1
- # Activated when this package is listed in a DSH profile's bundles.
2
- # The Host registers source configuration and authenticated RPC; the Web client
3
- # extends the native Plugins page.
4
- - insert:
5
- - id: registry-aggregator
6
- name: '@stolyarovmn/dsh-ui-registry-aggregator'
1
+ # Activated when this package is listed in a DSH profile's bundles.
2
+ # The Host registers source configuration and authenticated RPC; the Web client
3
+ # extends the native Plugins page.
4
+ - insert:
5
+ - id: registry-aggregator
6
+ name: '@stolyarovmn/dsh-ui-registry-aggregator'
package/icon.svg CHANGED
@@ -1,16 +1,16 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
- <defs>
3
- <linearGradient id="g" x1="8" y1="8" x2="56" y2="56" gradientUnits="userSpaceOnUse">
4
- <stop stop-color="#34D399"/>
5
- <stop offset="1" stop-color="#3B82F6"/>
6
- </linearGradient>
7
- </defs>
8
- <rect x="6" y="6" width="52" height="52" rx="15" fill="url(#g)"/>
9
- <path d="M18 19 32 32 46 19M18 45 32 32 46 45" fill="none" stroke="#fff" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
10
- <circle cx="18" cy="19" r="5" fill="#fff"/>
11
- <circle cx="46" cy="19" r="5" fill="#fff"/>
12
- <circle cx="18" cy="45" r="5" fill="#fff"/>
13
- <circle cx="46" cy="45" r="5" fill="#fff"/>
14
- <circle cx="32" cy="32" r="7" fill="#fff"/>
15
- <circle cx="32" cy="32" r="3" fill="url(#g)"/>
16
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
+ <defs>
3
+ <linearGradient id="g" x1="8" y1="8" x2="56" y2="56" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#34D399"/>
5
+ <stop offset="1" stop-color="#3B82F6"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect x="6" y="6" width="52" height="52" rx="15" fill="url(#g)"/>
9
+ <path d="M18 19 32 32 46 19M18 45 32 32 46 45" fill="none" stroke="#fff" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
10
+ <circle cx="18" cy="19" r="5" fill="#fff"/>
11
+ <circle cx="46" cy="19" r="5" fill="#fff"/>
12
+ <circle cx="18" cy="45" r="5" fill="#fff"/>
13
+ <circle cx="46" cy="45" r="5" fill="#fff"/>
14
+ <circle cx="32" cy="32" r="7" fill="#fff"/>
15
+ <circle cx="32" cy="32" r="3" fill="url(#g)"/>
16
+ </svg>