dsh-folia 2.0.1 → 2.0.2

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/lib/routes/inventory.js +101 -45
  2. package/package.json +225 -225
@@ -99,9 +99,23 @@ function rowStatusOf(probe) {
99
99
  */
100
100
  const FOLIA_SITE = 'https://folia-major-3t6.pages.dev';
101
101
  const FOLIA_TTL_MS = 60000;
102
- const FOLIA_TIMEOUT_MS = 4000;
103
- /** @type {{ at: number, items: any[] }} */
104
- let foliaCache = { at: 0, items: [] };
102
+ const FOLIA_TIMEOUT_DEFAULT_MS = 4000;
103
+ const FOLIA_TIMEOUT_MIN_MS = 1000;
104
+ const FOLIA_TIMEOUT_MAX_MS = 15000;
105
+
106
+ /**
107
+ * 拉取状态。**对用户可见**(随 inventory 下发 `siteSource`):站点不可达时界面要能
108
+ * 说清"为什么没有云端壁纸",而不是静默空库 —— 之前就是静默失败,排查时无从下手。
109
+ * @type {{ at: number, items: any[], status: { url: string, ok: boolean, count: number, ms: number, error: string|null } | null }}
110
+ */
111
+ let foliaCache = { at: 0, items: [], status: null };
112
+
113
+ /** 超时从 env 读,越界收敛到 [1s, 15s]。`DSH_FOLIA_SITE_TIMEOUT_MS=8000` 可放宽弱网。 */
114
+ function foliaTimeoutMs() {
115
+ const n = Number(process.env.DSH_FOLIA_SITE_TIMEOUT_MS);
116
+ if (!Number.isFinite(n) || n <= 0) return FOLIA_TIMEOUT_DEFAULT_MS;
117
+ return Math.min(FOLIA_TIMEOUT_MAX_MS, Math.max(FOLIA_TIMEOUT_MIN_MS, Math.round(n)));
118
+ }
105
119
 
106
120
  /** `DSH_FOLIA_SITE` → 归一化基址;`off`/空串表示停用。 */
107
121
  function foliaSiteBase() {
@@ -129,57 +143,91 @@ function foliaTypeOf(it) {
129
143
  }
130
144
 
131
145
  /**
132
- * 拉站点清单并折成 inventory 条目。永不抛;失败返回上一次的成功结果(或空)。
133
- * @returns {Promise<any[]>}
146
+ * 拉站点清单并折成 inventory 条目。永不抛。
147
+ *
148
+ * @param {boolean} [force] 忽略 TTL 强制重拉(客户端「重试」按钮走 `?refresh=1`)。
149
+ * @returns {Promise<{ items: any[], status: { url: string, ok: boolean, count: number, ms: number, error: string|null } | null }>}
150
+ *
151
+ * 失败分类(写进 `status.error`,让界面能说人话):
152
+ * `disabled` 通道被 `DSH_FOLIA_SITE=off` 关掉 · `timeout` 超时 · `tls` 证书问题
153
+ * `http-<code>` 状态码非 2xx · `json` 清单不是合法 JSON · `network` 其它网络错误
134
154
  */
135
- async function foliaRemote() {
155
+ async function foliaRemote(force = false) {
136
156
  const base = foliaSiteBase();
137
- if (!base) return [];
138
- if (Date.now() - foliaCache.at < FOLIA_TTL_MS) return foliaCache.items;
157
+ if (!base) return { items: [], status: null };
158
+ if (!force && Date.now() - foliaCache.at < FOLIA_TTL_MS) {
159
+ return { items: foliaCache.items, status: foliaCache.status };
160
+ }
139
161
 
162
+ const startedAt = Date.now();
163
+ const url = base + '/manifest.json';
140
164
  /** @type {any[]} */
141
- const items = [];
165
+ let items = [];
166
+ let error = null;
167
+
142
168
  try {
143
169
  const signal = typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function'
144
- ? AbortSignal.timeout(FOLIA_TIMEOUT_MS)
170
+ ? AbortSignal.timeout(foliaTimeoutMs())
145
171
  : undefined;
146
- const res = await fetch(base + '/manifest.json', { headers: { accept: 'application/json' }, signal });
147
- if (res.ok) {
148
- const doc = await res.json();
149
- const list = Array.isArray(doc && doc.images) ? doc.images : [];
150
- for (const it of list) {
151
- const type = foliaTypeOf(it);
152
- if (!type) continue;
153
- const file = String((it && (it.file || it.id)) || '');
154
- const media = foliaAbs(base, it && it.url);
155
- if (!media) continue;
156
- const ext = (file.split('.').pop() || (type === 'video' ? 'mp4' : 'jpg')).toLowerCase();
157
- items.push({
158
- id: 'folia-' + (file || media),
159
- title: String((it && it.title) || file || 'Folia'),
160
- type, // 'video' | 'image'
161
- contentrating: null,
162
- playable: true,
163
- media, // 绝对 URL
164
- mediaExt: '.' + ext,
165
- preview: foliaAbs(base, it && it.preview) || (type === 'image' ? media : null),
166
- frameUrl: null,
167
- schemeColor: null,
168
- sceneLiveSrc: null,
169
- sceneVideo: null,
170
- sceneAudio: null,
171
- propsUrl: null,
172
- liveFrame: null,
173
- source: 'folia', // 客户端可据此区分来源(未知字段会被忽略)
174
- });
172
+ const res = await fetch(url, { headers: { accept: 'application/json' }, signal });
173
+ if (!res.ok) {
174
+ error = 'http-' + res.status;
175
+ } else {
176
+ let doc;
177
+ try {
178
+ doc = await res.json();
179
+ } catch {
180
+ error = 'json';
181
+ }
182
+ if (doc) {
183
+ const list = Array.isArray(doc.images) ? doc.images : [];
184
+ for (const it of list) {
185
+ const type = foliaTypeOf(it);
186
+ if (!type) continue;
187
+ const file = String((it && (it.file || it.id)) || '');
188
+ const media = foliaAbs(base, it && it.url);
189
+ if (!media) continue;
190
+ const ext = (file.split('.').pop() || (type === 'video' ? 'mp4' : 'jpg')).toLowerCase();
191
+ items.push({
192
+ id: 'folia-' + (file || media),
193
+ title: String((it && it.title) || file || 'Folia'),
194
+ type, // 'video' | 'image'
195
+ contentrating: null,
196
+ playable: true,
197
+ media, // 绝对 URL
198
+ mediaExt: '.' + ext,
199
+ preview: foliaAbs(base, it && it.preview) || (type === 'image' ? media : null),
200
+ frameUrl: null,
201
+ schemeColor: null,
202
+ sceneLiveSrc: null,
203
+ sceneVideo: null,
204
+ sceneAudio: null,
205
+ propsUrl: null,
206
+ liveFrame: null,
207
+ source: 'folia', // 客户端可据此区分来源(未知字段会被忽略)
208
+ });
209
+ }
175
210
  }
176
211
  }
177
- } catch {
178
- // 站点不可达 / 超时 / JSON 坏:当作"这一轮没有远程源",本机库照常返回。
212
+ } catch (e) {
213
+ const code = String((e && (e.name || e.code)) || '');
214
+ const msg = String((e && e.message) || '');
215
+ if (/timeout|abort/i.test(code) || /timeout|aborted/i.test(msg)) error = 'timeout';
216
+ else if (/cert|tls|ssl/i.test(msg)) error = 'tls';
217
+ else error = 'network';
179
218
  }
219
+
220
+ const status = {
221
+ url,
222
+ ok: error === null,
223
+ count: items.length,
224
+ ms: Date.now() - startedAt,
225
+ error,
226
+ at: Date.now(),
227
+ };
180
228
  // 失败也写缓存:否则每次 /inventory 都要再等一次超时。
181
- foliaCache = { at: Date.now(), items };
182
- return items;
229
+ foliaCache = { at: Date.now(), items, status };
230
+ return { items, status };
183
231
  }
184
232
 
185
233
  export function registerInventoryRoutes(webServer, c) {
@@ -193,8 +241,13 @@ export function registerInventoryRoutes(webServer, c) {
193
241
  try {
194
242
  mediaOriginApi.observeAdapter(req); // 先观测再建库:媒体源起不起由本次请求的形态决定
195
243
  const payload = await buildInventory();
244
+ // `?refresh=1` 绕过站点源的 60s 缓存 —— 客户端「重试」按钮用,用户改完站点/网络后可立刻重拉。
245
+ let force = false;
246
+ try {
247
+ force = new URL(req.url || '/', 'http://x').searchParams.get('refresh') === '1';
248
+ } catch { /* URL 解析失败就当没传 */ }
196
249
  // 站点数据源:并进同一个壁纸库。失败/停用 ⇒ 原样返回本机库(本机功能永不受影响)。
197
- const remote = await foliaRemote();
250
+ const { items: remote, status: siteSource } = await foliaRemote(force);
198
251
  const merged = remote.length
199
252
  ? {
200
253
  ...payload,
@@ -204,12 +257,15 @@ export function registerInventoryRoutes(webServer, c) {
204
257
  portableCount: (payload.portableCount || 0) + remote.length,
205
258
  }
206
259
  : payload;
260
+ // 站点源的**状态面**(无论成功失败都下发):界面据此显示"站点 6 张"/"站点不可达(超时)",
261
+ // 而不是让用户对着空列表猜。字段缺席 = 更老的宿主 ⇒ 客户端按"不展示"处理。
262
+ const withSite = siteSource ? { ...merged, siteSource } : merged;
207
263
  // 组件行状态(只读,形状与失效口径见文件头「组件行状态」):探针不可用时**不写**该字段 ——
208
264
  // 消费方据此按"可用"渲染,而不是把"探测失败"渲染成"组件都没了"。
209
265
  const components = rowStatusOf(componentsProbe);
210
266
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
211
267
  res.setHeader('Cache-Control', 'no-store');
212
- res.end(JSON.stringify(components ? { ...merged, components } : merged));
268
+ res.end(JSON.stringify(components ? { ...withSite, components } : withSite));
213
269
  } catch (err) {
214
270
  res.statusCode = 500;
215
271
  res.setHeader('Content-Type', 'application/json');
package/package.json CHANGED
@@ -1,225 +1,225 @@
1
- {
2
- "name": "dsh-folia",
3
- "version": "2.0.1",
4
- "description": "Folia 壁纸引擎:把本机 Wallpaper Engine 壁纸搬进 DSH 界面(场景实时渲染 / 视频 / 网页),内置液态玻璃与 Folia 吉祥物,并可从自建站点拉取壁纸。单包形态(组件已合并)。",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=22.12.0",
8
- "dsh": "^0.2.0-rc.1"
9
- },
10
- "main": "lib/index.js",
11
- "types": "lib/types/index.d.ts",
12
- "icon": "./icon.png",
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/lehua-art/dsh-folia.git"
16
- },
17
- "keywords": [
18
- "dsh",
19
- "dsh-plugin",
20
- "deepseek-harness",
21
- "wallpaper",
22
- "folia",
23
- "theme",
24
- "background"
25
- ],
26
- "publishConfig": {
27
- "access": "public"
28
- },
29
- "exports": {
30
- ".": {
31
- "types": "./lib/types/index.d.ts",
32
- "default": "./lib/index.js"
33
- },
34
- "./client": {
35
- "types": "./lib/types/client.d.ts",
36
- "default": "./lib/client.js"
37
- },
38
- "./subpackage-boot.js": "./lib/subpackage-boot.js",
39
- "./cordis.patch.yml": "./cordis.patch.yml",
40
- "./package.json": "./package.json"
41
- },
42
- "files": [
43
- "icon.png",
44
- "lib/index.js",
45
- "lib/host-boot.js",
46
- "lib/log.js",
47
- "lib/notice.js",
48
- "lib/kernel/",
49
- "lib/kernel/data-dir.js",
50
- "lib/kernel/config.js",
51
- "lib/kernel/host-kernel.js",
52
- "lib/kernel/host-session.js",
53
- "lib/routes/",
54
- "lib/occlusion/",
55
- "lib/fontsets/",
56
- "lib/glass-presets/",
57
- "lib/about/",
58
- "lib/component-visibility.js",
59
- "lib/client.js",
60
- "lib/http-body.js",
61
- "lib/json-response.js",
62
- "lib/pkg-read.js",
63
- "lib/scene-manifest.js",
64
- "lib/settings-schema.js",
65
- "lib/subpackage-boot.js",
66
- "lib/media/",
67
- "lib/media/transcode.js",
68
- "lib/media/mp4-probe.js",
69
- "lib/media/scene-probe.js",
70
- "lib/media/video-preview.js",
71
- "lib/media/frame-store.js",
72
- "lib/media/media-dirs.js",
73
- "lib/media-origin.js",
74
- "lib/inventory.js",
75
- "lib/serve.js",
76
- "lib/faststart.js",
77
- "lib/cache-dir.js",
78
- "lib/upload-store.js",
79
- "lib/diag-trace.js",
80
- "lib/http-lifecycle.js",
81
- "lib/mp4-vfs.js",
82
- "lib/startup-sweep.js",
83
- "lib/fs-paths.js",
84
- "lib/upload-dir.js",
85
- "lib/wallpaper-scan.js",
86
- "lib/steam-discovery.js",
87
- "lib/webwallgl/",
88
- "lib/we-assets.js",
89
- "lib/shim-seed.js",
90
- "lib/we-props.js",
91
- "lib/we-focus-guard.js",
92
- "lib/types/index.d.ts",
93
- "lib/types/client.d.ts",
94
- "cordis.patch.yml",
95
- "assets/readme/hero-light.png",
96
- "assets/readme/hero-dark.png",
97
- "assets/readme/key-lang-zh-light.png",
98
- "assets/readme/key-lang-zh-dark.png",
99
- "assets/readme/key-lang-en-light.png",
100
- "assets/readme/key-lang-en-dark.png",
101
- "assets/readme/key-lang-start-light.png",
102
- "assets/readme/key-lang-start-dark.png",
103
- "assets/readme/key-get-light.png",
104
- "assets/readme/key-get-dark.png",
105
- "assets/readme/key-setup-light.png",
106
- "assets/readme/key-setup-dark.png",
107
- "assets/readme/key-docs-light.png",
108
- "assets/readme/key-docs-dark.png",
109
- "assets/readme/key-release-light.png",
110
- "assets/readme/key-release-dark.png",
111
- "assets/readme/stat-version-light.png",
112
- "assets/readme/stat-version-dark.png",
113
- "assets/readme/stat-formats-light.png",
114
- "assets/readme/stat-formats-dark.png",
115
- "assets/readme/stat-mascots-light.png",
116
- "assets/readme/stat-mascots-dark.png",
117
- "assets/readme/stat-modules-light.png",
118
- "assets/readme/stat-modules-dark.png",
119
- "assets/readme/section-intro-light.png",
120
- "assets/readme/section-intro-dark.png",
121
- "assets/readme/section-preview-light.png",
122
- "assets/readme/section-preview-dark.png",
123
- "assets/readme/section-start-light.png",
124
- "assets/readme/section-start-dark.png",
125
- "assets/readme/section-index-light.png",
126
- "assets/readme/section-index-dark.png",
127
- "assets/readme/section-features-light.png",
128
- "assets/readme/section-features-dark.png",
129
- "assets/readme/section-formats-light.png",
130
- "assets/readme/section-formats-dark.png",
131
- "assets/readme/section-install-light.png",
132
- "assets/readme/section-install-dark.png",
133
- "assets/readme/section-usage-light.png",
134
- "assets/readme/section-usage-dark.png",
135
- "assets/readme/section-pet-light.png",
136
- "assets/readme/section-pet-dark.png",
137
- "assets/readme/section-config-light.png",
138
- "assets/readme/section-config-dark.png",
139
- "assets/readme/section-compat-light.png",
140
- "assets/readme/section-compat-dark.png",
141
- "assets/readme/section-develop-light.png",
142
- "assets/readme/section-develop-dark.png",
143
- "assets/readme/section-community-light.png",
144
- "assets/readme/section-community-dark.png",
145
- "assets/readme/section-credits-light.png",
146
- "assets/readme/section-credits-dark.png",
147
- "assets/readme/section-support-light.png",
148
- "assets/readme/section-support-dark.png",
149
- "assets/readme/section-stars-light.png",
150
- "assets/readme/section-stars-dark.png",
151
- "assets/readme/SOURCES.md",
152
- "assets/readme/OFL-Jersey20.txt",
153
- "assets/about/sponsor-fish.png",
154
- "assets/readme/mascot-eating-rice-1280x1784.jpg",
155
- "README.md",
156
- "README.en.md",
157
- "README.beginner.md",
158
- "lib/components/"
159
- ],
160
- "dsh": {
161
- "bundle": {
162
- "patch": "./cordis.patch.yml"
163
- },
164
- "client": {
165
- "inject": [
166
- "@deepseek-ai/dsh-client-runtime"
167
- ],
168
- "platform": "web",
169
- "immediately": true
170
- }
171
- },
172
- "license": "MIT",
173
- "scripts": {
174
- "build": "node scripts/build-client.mjs",
175
- "install:source": "node scripts/install-source.mjs",
176
- "install:release": "node scripts/install-release.mjs",
177
- "pack:release": "node scripts/pack-release.mjs",
178
- "verify:deployment": "node test/verify-deployment.mjs",
179
- "verify:pet-link": "node test/verify-pet-link.mjs",
180
- "verify:pet-link:integration": "node test/verify-pet-hotplug-integration.mjs",
181
- "verify:pet-link:browser": "node test/verify-pet-tuner-browser.mjs",
182
- "verify": "node test/run-guards.mjs verify",
183
- "verify:docs": "node test/run-guards.mjs docs",
184
- "verify:bridge": "node test/verify-bridge-ci.mjs --provision",
185
- "verify:bridge:strict": "node test/verify-media-bridge.mjs --provision",
186
- "verify:e2e": "node test/e2e-web-media-origin.mjs",
187
- "lint": "eslint .",
188
- "typecheck": "tsc --noEmit -p tsconfig.json",
189
- "verify:static": "node test/verify-static.mjs",
190
- "smoke": "node test/run-guards.mjs smoke",
191
- "verify:all": "node test/run-guards.mjs all",
192
- "prepack": "node scripts/prepare.mjs"
193
- },
194
- "peerDependencies": {
195
- "@deepseek-ai/cordis": "^4.0.4",
196
- "@deepseek-ai/dsh-client-runtime": ">=0.1.5-rc.1",
197
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1",
198
- "@deepseek-ai/dsh-host-webserver": ">=0.1.5-rc.1",
199
- "react": "^18.2.0"
200
- },
201
- "peerDependenciesMeta": {
202
- "@deepseek-ai/dsh-client-runtime": {
203
- "optional": true
204
- },
205
- "@deepseek-ai/dsh-client-ui-slots": {
206
- "optional": true
207
- },
208
- "@deepseek-ai/dsh-host-webserver": {
209
- "optional": true
210
- }
211
- },
212
- "dependencies": {
213
- "webwallgl": "^3.0.0",
214
- "x11": "^4.3.1"
215
- },
216
- "overrides": {
217
- "js-yaml": "4.3.2"
218
- },
219
- "devDependencies": {
220
- "@eslint/js": "^10.0.1",
221
- "@types/node": "^26.6.5",
222
- "eslint": "^10.12.0",
223
- "typescript": "^7.0.2"
224
- }
225
- }
1
+ {
2
+ "name": "dsh-folia",
3
+ "version": "2.0.2",
4
+ "description": "Folia 壁纸引擎:把本机 Wallpaper Engine 壁纸搬进 DSH 界面(场景实时渲染 / 视频 / 网页),内置液态玻璃与 Folia 吉祥物,并可从自建站点拉取壁纸。单包形态(组件已合并)。",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": "\u003e=22.12.0",
8
+ "dsh": "^0.2.0-rc.1"
9
+ },
10
+ "main": "lib/index.js",
11
+ "types": "lib/types/index.d.ts",
12
+ "icon": "./icon.png",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/lehua-art/dsh-folia.git"
16
+ },
17
+ "keywords": [
18
+ "dsh",
19
+ "dsh-plugin",
20
+ "deepseek-harness",
21
+ "wallpaper",
22
+ "folia",
23
+ "theme",
24
+ "background"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./lib/types/index.d.ts",
32
+ "default": "./lib/index.js"
33
+ },
34
+ "./client": {
35
+ "types": "./lib/types/client.d.ts",
36
+ "default": "./lib/client.js"
37
+ },
38
+ "./subpackage-boot.js": "./lib/subpackage-boot.js",
39
+ "./cordis.patch.yml": "./cordis.patch.yml",
40
+ "./package.json": "./package.json"
41
+ },
42
+ "files": [
43
+ "icon.png",
44
+ "lib/index.js",
45
+ "lib/host-boot.js",
46
+ "lib/log.js",
47
+ "lib/notice.js",
48
+ "lib/kernel/",
49
+ "lib/kernel/data-dir.js",
50
+ "lib/kernel/config.js",
51
+ "lib/kernel/host-kernel.js",
52
+ "lib/kernel/host-session.js",
53
+ "lib/routes/",
54
+ "lib/occlusion/",
55
+ "lib/fontsets/",
56
+ "lib/glass-presets/",
57
+ "lib/about/",
58
+ "lib/component-visibility.js",
59
+ "lib/client.js",
60
+ "lib/http-body.js",
61
+ "lib/json-response.js",
62
+ "lib/pkg-read.js",
63
+ "lib/scene-manifest.js",
64
+ "lib/settings-schema.js",
65
+ "lib/subpackage-boot.js",
66
+ "lib/media/",
67
+ "lib/media/transcode.js",
68
+ "lib/media/mp4-probe.js",
69
+ "lib/media/scene-probe.js",
70
+ "lib/media/video-preview.js",
71
+ "lib/media/frame-store.js",
72
+ "lib/media/media-dirs.js",
73
+ "lib/media-origin.js",
74
+ "lib/inventory.js",
75
+ "lib/serve.js",
76
+ "lib/faststart.js",
77
+ "lib/cache-dir.js",
78
+ "lib/upload-store.js",
79
+ "lib/diag-trace.js",
80
+ "lib/http-lifecycle.js",
81
+ "lib/mp4-vfs.js",
82
+ "lib/startup-sweep.js",
83
+ "lib/fs-paths.js",
84
+ "lib/upload-dir.js",
85
+ "lib/wallpaper-scan.js",
86
+ "lib/steam-discovery.js",
87
+ "lib/webwallgl/",
88
+ "lib/we-assets.js",
89
+ "lib/shim-seed.js",
90
+ "lib/we-props.js",
91
+ "lib/we-focus-guard.js",
92
+ "lib/types/index.d.ts",
93
+ "lib/types/client.d.ts",
94
+ "cordis.patch.yml",
95
+ "assets/readme/hero-light.png",
96
+ "assets/readme/hero-dark.png",
97
+ "assets/readme/key-lang-zh-light.png",
98
+ "assets/readme/key-lang-zh-dark.png",
99
+ "assets/readme/key-lang-en-light.png",
100
+ "assets/readme/key-lang-en-dark.png",
101
+ "assets/readme/key-lang-start-light.png",
102
+ "assets/readme/key-lang-start-dark.png",
103
+ "assets/readme/key-get-light.png",
104
+ "assets/readme/key-get-dark.png",
105
+ "assets/readme/key-setup-light.png",
106
+ "assets/readme/key-setup-dark.png",
107
+ "assets/readme/key-docs-light.png",
108
+ "assets/readme/key-docs-dark.png",
109
+ "assets/readme/key-release-light.png",
110
+ "assets/readme/key-release-dark.png",
111
+ "assets/readme/stat-version-light.png",
112
+ "assets/readme/stat-version-dark.png",
113
+ "assets/readme/stat-formats-light.png",
114
+ "assets/readme/stat-formats-dark.png",
115
+ "assets/readme/stat-mascots-light.png",
116
+ "assets/readme/stat-mascots-dark.png",
117
+ "assets/readme/stat-modules-light.png",
118
+ "assets/readme/stat-modules-dark.png",
119
+ "assets/readme/section-intro-light.png",
120
+ "assets/readme/section-intro-dark.png",
121
+ "assets/readme/section-preview-light.png",
122
+ "assets/readme/section-preview-dark.png",
123
+ "assets/readme/section-start-light.png",
124
+ "assets/readme/section-start-dark.png",
125
+ "assets/readme/section-index-light.png",
126
+ "assets/readme/section-index-dark.png",
127
+ "assets/readme/section-features-light.png",
128
+ "assets/readme/section-features-dark.png",
129
+ "assets/readme/section-formats-light.png",
130
+ "assets/readme/section-formats-dark.png",
131
+ "assets/readme/section-install-light.png",
132
+ "assets/readme/section-install-dark.png",
133
+ "assets/readme/section-usage-light.png",
134
+ "assets/readme/section-usage-dark.png",
135
+ "assets/readme/section-pet-light.png",
136
+ "assets/readme/section-pet-dark.png",
137
+ "assets/readme/section-config-light.png",
138
+ "assets/readme/section-config-dark.png",
139
+ "assets/readme/section-compat-light.png",
140
+ "assets/readme/section-compat-dark.png",
141
+ "assets/readme/section-develop-light.png",
142
+ "assets/readme/section-develop-dark.png",
143
+ "assets/readme/section-community-light.png",
144
+ "assets/readme/section-community-dark.png",
145
+ "assets/readme/section-credits-light.png",
146
+ "assets/readme/section-credits-dark.png",
147
+ "assets/readme/section-support-light.png",
148
+ "assets/readme/section-support-dark.png",
149
+ "assets/readme/section-stars-light.png",
150
+ "assets/readme/section-stars-dark.png",
151
+ "assets/readme/SOURCES.md",
152
+ "assets/readme/OFL-Jersey20.txt",
153
+ "assets/about/sponsor-fish.png",
154
+ "assets/readme/mascot-eating-rice-1280x1784.jpg",
155
+ "README.md",
156
+ "README.en.md",
157
+ "README.beginner.md",
158
+ "lib/components/"
159
+ ],
160
+ "dsh": {
161
+ "bundle": {
162
+ "patch": "./cordis.patch.yml"
163
+ },
164
+ "client": {
165
+ "inject": [
166
+ "@deepseek-ai/dsh-client-runtime"
167
+ ],
168
+ "platform": "web",
169
+ "immediately": true
170
+ }
171
+ },
172
+ "license": "MIT",
173
+ "scripts": {
174
+ "build": "node scripts/build-client.mjs",
175
+ "install:source": "node scripts/install-source.mjs",
176
+ "install:release": "node scripts/install-release.mjs",
177
+ "pack:release": "node scripts/pack-release.mjs",
178
+ "verify:deployment": "node test/verify-deployment.mjs",
179
+ "verify:pet-link": "node test/verify-pet-link.mjs",
180
+ "verify:pet-link:integration": "node test/verify-pet-hotplug-integration.mjs",
181
+ "verify:pet-link:browser": "node test/verify-pet-tuner-browser.mjs",
182
+ "verify": "node test/run-guards.mjs verify",
183
+ "verify:docs": "node test/run-guards.mjs docs",
184
+ "verify:bridge": "node test/verify-bridge-ci.mjs --provision",
185
+ "verify:bridge:strict": "node test/verify-media-bridge.mjs --provision",
186
+ "verify:e2e": "node test/e2e-web-media-origin.mjs",
187
+ "lint": "eslint .",
188
+ "typecheck": "tsc --noEmit -p tsconfig.json",
189
+ "verify:static": "node test/verify-static.mjs",
190
+ "smoke": "node test/run-guards.mjs smoke",
191
+ "verify:all": "node test/run-guards.mjs all",
192
+ "prepack": "node scripts/prepare.mjs"
193
+ },
194
+ "peerDependencies": {
195
+ "@deepseek-ai/cordis": "^4.0.4",
196
+ "@deepseek-ai/dsh-client-runtime": "\u003e=0.1.5-rc.1",
197
+ "@deepseek-ai/dsh-client-ui-slots": "\u003e=0.1.5-rc.1",
198
+ "@deepseek-ai/dsh-host-webserver": "\u003e=0.1.5-rc.1",
199
+ "react": "^18.2.0"
200
+ },
201
+ "peerDependenciesMeta": {
202
+ "@deepseek-ai/dsh-client-runtime": {
203
+ "optional": true
204
+ },
205
+ "@deepseek-ai/dsh-client-ui-slots": {
206
+ "optional": true
207
+ },
208
+ "@deepseek-ai/dsh-host-webserver": {
209
+ "optional": true
210
+ }
211
+ },
212
+ "dependencies": {
213
+ "webwallgl": "^3.0.0",
214
+ "x11": "^4.3.1"
215
+ },
216
+ "overrides": {
217
+ "js-yaml": "4.3.2"
218
+ },
219
+ "devDependencies": {
220
+ "@eslint/js": "^10.0.1",
221
+ "@types/node": "^26.6.5",
222
+ "eslint": "^10.12.0",
223
+ "typescript": "^7.0.2"
224
+ }
225
+ }