@wenaixi/dsh-superpower 7.6.0 → 7.7.1
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/README.md +2 -1
- package/README.zh.md +2 -1
- package/lib/catalog.d.ts +4 -3
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +63 -5
- package/lib/catalog.js.map +1 -1
- package/lib/client.js +379 -126
- package/lib/superpowers.d.ts +1 -1
- package/lib/superpowers.d.ts.map +1 -1
- package/lib/superpowers.js +16 -12
- package/lib/superpowers.js.map +1 -1
- package/lib/switches.d.ts +38 -20
- package/lib/switches.d.ts.map +1 -1
- package/lib/switches.js +190 -66
- package/lib/switches.js.map +1 -1
- package/package.json +3 -2
package/lib/client.js
CHANGED
|
@@ -31,6 +31,7 @@ window.__ModuleLoader__.load({
|
|
|
31
31
|
var PACKAGE_NAME = '@wenaixi/dsh-superpower';
|
|
32
32
|
var NS = 'dsh-superpower';
|
|
33
33
|
var DISABLED_FIELD = 'disabled';
|
|
34
|
+
var LANGUAGE_FIELD = 'language';
|
|
34
35
|
/* v7.3.0 及之前的双侧禁言表。面板写入成功后会把它们 unset,
|
|
35
36
|
这里仍需列出:迁移那批操作的路径必须与 schema 里的字段名逐字一致。 */
|
|
36
37
|
var LEGACY_FIELDS = ['modelDisabled', 'userDisabled'];
|
|
@@ -140,6 +141,12 @@ window.__ModuleLoader__.load({
|
|
|
140
141
|
'@media (prefers-reduced-motion:reduce){.spSw *{transition:none!important}}',
|
|
141
142
|
].join('\n');
|
|
142
143
|
|
|
144
|
+
/**
|
|
145
|
+
* 已知标准技能名白名单映射。
|
|
146
|
+
*/
|
|
147
|
+
var KNOWN_SKILL_MAP = {};
|
|
148
|
+
SKILL_CATALOG.forEach(function (skill) { KNOWN_SKILL_MAP[skill.name] = true; });
|
|
149
|
+
|
|
143
150
|
/**
|
|
144
151
|
* 读取禁言字典里某个技能是否被关闭。缺项与 falsy 一律视为开启。
|
|
145
152
|
*/
|
|
@@ -148,105 +155,384 @@ window.__ModuleLoader__.load({
|
|
|
148
155
|
}
|
|
149
156
|
|
|
150
157
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* 「新表写了一部分、旧表还留着」的中间态,也省掉每技能一次额外往返。
|
|
156
|
-
* op 为 enable 时 unset 路径即恢复继承的默认值。
|
|
158
|
+
* 容灾清洗并提取禁言字典。
|
|
159
|
+
* 1. 过滤非合法技能名与原型污染键;
|
|
160
|
+
* 2. 宽容识别非标真值(true, "true", 1, "1", "yes", "on", "disabled");
|
|
161
|
+
* 3. 忽略假值(false, "false", 0, "no", "off" 等)。
|
|
157
162
|
*/
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
function extractCleanDisabled(value) {
|
|
164
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
165
|
+
return Object.create(null);
|
|
166
|
+
}
|
|
167
|
+
var clean = Object.create(null);
|
|
168
|
+
Object.keys(value).forEach(function (key) {
|
|
169
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') return;
|
|
170
|
+
if (!KNOWN_SKILL_MAP[key]) return;
|
|
171
|
+
var val = value[key];
|
|
172
|
+
if (
|
|
173
|
+
val === true ||
|
|
174
|
+
val === 'true' ||
|
|
175
|
+
val === 1 ||
|
|
176
|
+
val === '1' ||
|
|
177
|
+
val === 'yes' ||
|
|
178
|
+
val === 'on' ||
|
|
179
|
+
val === 'disabled'
|
|
180
|
+
) {
|
|
181
|
+
clean[key] = true;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return clean;
|
|
185
|
+
}
|
|
160
186
|
|
|
161
187
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
188
|
+
* 读取当前语言偏好(三态,含容灾自愈提取):
|
|
189
|
+
* 支持从非标语言码(如 'zh-CN', 'zh_CN', 'en-US', 'chinese' 等)自愈归一化;
|
|
190
|
+
* 缺项或未知输入返回 undefined(跟随宿主)。
|
|
164
191
|
*/
|
|
165
192
|
function readLanguage(value) {
|
|
166
193
|
var raw = value && value[LANGUAGE_FIELD];
|
|
167
|
-
|
|
194
|
+
if (typeof raw !== 'string') return undefined;
|
|
195
|
+
var lower = raw.trim().toLowerCase().replace(/_/g, '-');
|
|
196
|
+
if (lower === 'zh' || lower.indexOf('zh-') === 0 || lower === 'chinese') return 'zh';
|
|
197
|
+
if (lower === 'en' || lower.indexOf('en-') === 0 || lower === 'english') return 'en';
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 纯函数探测配置是否包含损坏数据、非标格式或需要自愈修复的结构。
|
|
203
|
+
*/
|
|
204
|
+
function isConfigCorrupted(value) {
|
|
205
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return true;
|
|
206
|
+
var rawDisabled = value[DISABLED_FIELD];
|
|
207
|
+
if (rawDisabled !== undefined && rawDisabled !== null) {
|
|
208
|
+
if (typeof rawDisabled !== 'object' || Array.isArray(rawDisabled)) return true;
|
|
209
|
+
var keys = Object.keys(rawDisabled);
|
|
210
|
+
for (var i = 0; i < keys.length; i++) {
|
|
211
|
+
var k = keys[i];
|
|
212
|
+
if (!KNOWN_SKILL_MAP[k]) return true;
|
|
213
|
+
if (rawDisabled[k] !== true) return true; // 非标准布尔值或残留假值
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
var rawLang = value[LANGUAGE_FIELD];
|
|
217
|
+
if (rawLang !== undefined && rawLang !== null && rawLang !== 'zh' && rawLang !== 'en') {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
168
221
|
}
|
|
169
222
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
223
|
+
/**
|
|
224
|
+
* 客户端配置控制器深度模块 (Deep Module):
|
|
225
|
+
* 将 DSH ConfigForm 订阅、批处理 ops 拍平、旧表原子继承、disposed 拦截与堆栈归集彻底封闭在门后。
|
|
226
|
+
*/
|
|
227
|
+
class SwitchPanelModel {
|
|
228
|
+
constructor(scope, options) {
|
|
229
|
+
this.scope = scope;
|
|
230
|
+
this.t = (options && options.t) || ((k) => k);
|
|
231
|
+
this.allNames = (options && options.allNames) || [];
|
|
232
|
+
this.skills = (options && options.skills) || SKILL_CATALOG;
|
|
233
|
+
this.keyword = '';
|
|
234
|
+
this.listeners = new Set();
|
|
235
|
+
this.pending = {};
|
|
236
|
+
this.failures = {};
|
|
237
|
+
this.unsubscribe = null;
|
|
238
|
+
this._bindScope(scope);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
_bindScope(scope) {
|
|
242
|
+
if (this.scope !== scope) {
|
|
243
|
+
if (this.unsubscribe) {
|
|
244
|
+
this.unsubscribe();
|
|
245
|
+
this.unsubscribe = null;
|
|
177
246
|
}
|
|
247
|
+
this.scope = scope;
|
|
248
|
+
}
|
|
249
|
+
if (this.scope && typeof this.scope.subscribe === 'function' && !this.unsubscribe) {
|
|
250
|
+
this.unsubscribe = this.scope.subscribe(() => this._notify());
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
updateScope(nextScope) {
|
|
255
|
+
this._bindScope(nextScope);
|
|
256
|
+
this._notify();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
subscribe(listener) {
|
|
260
|
+
this.listeners.add(listener);
|
|
261
|
+
return () => this.listeners.delete(listener);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
_notify() {
|
|
265
|
+
this.listeners.forEach((fn) => {
|
|
266
|
+
try { fn(); } catch (e) {}
|
|
178
267
|
});
|
|
179
268
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
269
|
+
|
|
270
|
+
getSnapshot() {
|
|
271
|
+
var snap = (this.scope && typeof this.scope.getSnapshot === 'function')
|
|
272
|
+
? this.scope.getSnapshot()
|
|
273
|
+
: { status: 'loading', writable: false, value: {} };
|
|
274
|
+
var value = snap.value || {};
|
|
275
|
+
var rawDisabled = value[DISABLED_FIELD];
|
|
276
|
+
var cleanDisabled = extractCleanDisabled(rawDisabled);
|
|
277
|
+
var rawDisabledExists = rawDisabled && typeof rawDisabled === 'object' && !Array.isArray(rawDisabled);
|
|
278
|
+
var legacyActive = !rawDisabledExists || Object.keys(cleanDisabled).length === 0;
|
|
279
|
+
|
|
280
|
+
var disabled;
|
|
281
|
+
if (!legacyActive && rawDisabledExists) {
|
|
282
|
+
disabled = cleanDisabled;
|
|
183
283
|
} else {
|
|
184
|
-
|
|
284
|
+
var legModel = extractCleanDisabled(value.modelDisabled);
|
|
285
|
+
var legUser = extractCleanDisabled(value.userDisabled);
|
|
286
|
+
disabled = Object.assign({}, legModel, legUser);
|
|
185
287
|
}
|
|
186
|
-
});
|
|
187
|
-
return ops.concat(LEGACY_FIELDS.map(function (field) {
|
|
188
|
-
return { op: 'unset', path: [field] };
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
288
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
289
|
+
var language = readLanguage(value);
|
|
290
|
+
var corrupted = isConfigCorrupted(value);
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
status: snap.status || 'ready',
|
|
294
|
+
writable: snap.writable !== false && snap.mode !== 'memory',
|
|
295
|
+
disabled: disabled,
|
|
296
|
+
legacyActive: legacyActive,
|
|
297
|
+
language: language,
|
|
298
|
+
langConfigured: language !== undefined,
|
|
299
|
+
langValue: language !== undefined ? language : 'auto',
|
|
300
|
+
keyword: this.keyword,
|
|
301
|
+
corrupted: corrupted,
|
|
302
|
+
pending: this.pending,
|
|
303
|
+
failures: this.failures,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
buildRepairOps() {
|
|
308
|
+
var snap = this.getSnapshot();
|
|
309
|
+
var ops = [];
|
|
310
|
+
var disabled = snap.disabled;
|
|
311
|
+
Object.keys(disabled).forEach(function (name) {
|
|
312
|
+
if (disabled[name] === true && KNOWN_SKILL_MAP[name]) {
|
|
313
|
+
ops.push({ op: 'set', path: [DISABLED_FIELD, name], value: true });
|
|
314
|
+
}
|
|
202
315
|
});
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
var next = clear(prev);
|
|
220
|
-
var message = t('writeFailed') + ': ' + String(error && error.message ? error.message : error);
|
|
221
|
-
names.forEach(function (name) { next[name] = message; });
|
|
222
|
-
return next;
|
|
316
|
+
var rawValue = (this.scope && typeof this.scope.getSnapshot === 'function' ? this.scope.getSnapshot().value : {}) || {};
|
|
317
|
+
var rawDisabled = rawValue[DISABLED_FIELD];
|
|
318
|
+
if (rawDisabled && typeof rawDisabled === 'object' && !Array.isArray(rawDisabled)) {
|
|
319
|
+
Object.keys(rawDisabled).forEach(function (k) {
|
|
320
|
+
if (!disabled[k] || !KNOWN_SKILL_MAP[k]) {
|
|
321
|
+
ops.push({ op: 'unset', path: [DISABLED_FIELD, k] });
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (snap.language !== undefined) {
|
|
326
|
+
ops.push({ op: 'set', path: [LANGUAGE_FIELD], value: snap.language });
|
|
327
|
+
} else if (rawValue[LANGUAGE_FIELD] !== undefined) {
|
|
328
|
+
ops.push({ op: 'unset', path: [LANGUAGE_FIELD] });
|
|
329
|
+
}
|
|
330
|
+
LEGACY_FIELDS.forEach(function (field) {
|
|
331
|
+
ops.push({ op: 'unset', path: [field] });
|
|
223
332
|
});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
333
|
+
return ops;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
async repairConfig(force) {
|
|
337
|
+
var snap = this.getSnapshot();
|
|
338
|
+
if ((!force && !snap.corrupted) || !snap.writable || !this.scope || this.scope.disposed) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
if (this._repairing) return false;
|
|
342
|
+
this._repairing = true;
|
|
343
|
+
try {
|
|
344
|
+
var ops = this.buildRepairOps();
|
|
345
|
+
if (ops.length > 0) {
|
|
346
|
+
return await this.scope.mutate(ops);
|
|
347
|
+
}
|
|
348
|
+
} catch (e) {
|
|
349
|
+
console.error('[dsh-superpower] repairConfig failed:', e);
|
|
350
|
+
} finally {
|
|
351
|
+
this._repairing = false;
|
|
352
|
+
}
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
setKeyword(query) {
|
|
357
|
+
var next = String(query || '');
|
|
358
|
+
if (this.keyword !== next) {
|
|
359
|
+
this.keyword = next;
|
|
360
|
+
this._notify();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
getVisibleSkills(hostActive) {
|
|
365
|
+
var snap = this.getSnapshot();
|
|
366
|
+
var language = snap.language;
|
|
367
|
+
var effective = language === undefined ? (hostActive === 'en' ? 'en' : 'zh') : language;
|
|
368
|
+
var lower = this.keyword.trim().toLowerCase();
|
|
369
|
+
var list = this.skills;
|
|
370
|
+
var skillText = function (skill) {
|
|
371
|
+
return effective === 'en' && skill.descriptionEn ? skill.descriptionEn : skill.description;
|
|
372
|
+
};
|
|
373
|
+
var matches = lower === ''
|
|
374
|
+
? list
|
|
375
|
+
: list.filter(function (skill) {
|
|
376
|
+
var name = skill.name.toLowerCase();
|
|
377
|
+
return name.indexOf(lower) >= 0
|
|
378
|
+
|| skill.description.toLowerCase().indexOf(lower) >= 0
|
|
379
|
+
|| (skill.descriptionEn || '').toLowerCase().indexOf(lower) >= 0;
|
|
380
|
+
});
|
|
381
|
+
return matches.map(function (skill) {
|
|
382
|
+
return Object.assign({}, skill, { displayText: skillText(skill) });
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
_buildOps(names, op, legacyCarry) {
|
|
387
|
+
var list = Array.isArray(names) ? names : [names];
|
|
388
|
+
var ops = [];
|
|
389
|
+
if (legacyCarry) {
|
|
390
|
+
Object.keys(legacyCarry).forEach(function (key) {
|
|
391
|
+
if (legacyCarry[key] === true && list.indexOf(key) < 0) {
|
|
392
|
+
ops.push({ op: 'set', path: [DISABLED_FIELD, key], value: true });
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
list.forEach(function (name) {
|
|
397
|
+
if (op === 'disable') {
|
|
398
|
+
ops.push({ op: 'set', path: [DISABLED_FIELD, name], value: true });
|
|
399
|
+
} else {
|
|
400
|
+
ops.push({ op: 'unset', path: [DISABLED_FIELD, name] });
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
return ops.concat(LEGACY_FIELDS.map(function (field) {
|
|
404
|
+
return { op: 'unset', path: [field] };
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async _submit(names, ops) {
|
|
409
|
+
if (!this.scope || this.scope.disposed || typeof this.scope.mutate !== 'function') {
|
|
410
|
+
var err = new Error(this.t('hostUnavailable'));
|
|
411
|
+
console.error('[dsh-superpower] form.mutate failed:', err);
|
|
412
|
+
this._setFailures(names, this.t('writeFailed') + ': ' + err.message);
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
this._setPending(names, true);
|
|
417
|
+
this._clearFailures(names);
|
|
418
|
+
|
|
419
|
+
try {
|
|
420
|
+
var accepted = await this.scope.mutate(ops);
|
|
421
|
+
if (accepted === false) {
|
|
422
|
+
throw new Error(this.t('writeFailed'));
|
|
423
|
+
}
|
|
424
|
+
this._clearFailures(names);
|
|
425
|
+
return true;
|
|
426
|
+
} catch (error) {
|
|
427
|
+
console.error('[dsh-superpower] form.mutate failed:', error);
|
|
428
|
+
var msg = this.t('writeFailed') + ': ' + String(error && error.message ? error.message : error);
|
|
429
|
+
this._setFailures(names, msg);
|
|
430
|
+
return false;
|
|
431
|
+
} finally {
|
|
432
|
+
this._setPending(names, false);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
_setPending(names, isPending) {
|
|
437
|
+
var next = Object.assign({}, this.pending);
|
|
438
|
+
names.forEach(function (name) {
|
|
439
|
+
if (isPending) next[name] = true;
|
|
440
|
+
else delete next[name];
|
|
441
|
+
});
|
|
442
|
+
this.pending = next;
|
|
443
|
+
this._notify();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_setFailures(names, message) {
|
|
447
|
+
var next = Object.assign({}, this.failures);
|
|
448
|
+
names.forEach(function (name) { next[name] = message; });
|
|
449
|
+
this.failures = next;
|
|
450
|
+
this._notify();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
_clearFailures(names) {
|
|
454
|
+
var next = Object.assign({}, this.failures);
|
|
455
|
+
var changed = false;
|
|
456
|
+
names.forEach(function (name) {
|
|
457
|
+
if (next[name]) {
|
|
458
|
+
delete next[name];
|
|
459
|
+
changed = true;
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
if (changed) {
|
|
463
|
+
this.failures = next;
|
|
464
|
+
this._notify();
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
toggle(name, nextState) {
|
|
469
|
+
var snap = this.getSnapshot();
|
|
470
|
+
var op = nextState ? 'enable' : 'disable';
|
|
471
|
+
var legacyCarry = snap.legacyActive ? snap.disabled : null;
|
|
472
|
+
var ops = this._buildOps([name], op, legacyCarry);
|
|
473
|
+
return this._submit([name], ops);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
setLanguage(next) {
|
|
477
|
+
var ops = next === 'auto'
|
|
478
|
+
? [{ op: 'unset', path: [LANGUAGE_FIELD] }]
|
|
479
|
+
: [{ op: 'set', path: [LANGUAGE_FIELD], value: next }];
|
|
480
|
+
return this._submit(['language'], ops);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
enableAll() {
|
|
484
|
+
var ops = this._buildOps(this.allNames, 'enable');
|
|
485
|
+
return this._submit(this.allNames, ops);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
disableAll() {
|
|
489
|
+
var ops = this._buildOps(this.allNames, 'disable');
|
|
490
|
+
return this._submit(this.allNames, ops);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
resetAll() {
|
|
494
|
+
// Q2 裁决:恢复默认纯粹重置技能禁言表,保持语言偏好正交独立
|
|
495
|
+
return this.enableAll();
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
dispose() {
|
|
499
|
+
if (this.unsubscribe) {
|
|
500
|
+
this.unsubscribe();
|
|
501
|
+
this.unsubscribe = null;
|
|
502
|
+
}
|
|
503
|
+
this.listeners.clear();
|
|
504
|
+
}
|
|
227
505
|
}
|
|
228
506
|
|
|
229
507
|
/**
|
|
230
|
-
*
|
|
508
|
+
* 技能开关面板 (View)。纯渲染视图,完全由 SwitchPanelModel 控制器驱动。
|
|
231
509
|
*
|
|
232
|
-
* props.
|
|
233
|
-
* props.actions 是本面板独占的写操作面。
|
|
510
|
+
* props.actions.form 是本面板绑定的 ConfigForm 控制器。
|
|
234
511
|
*/
|
|
235
512
|
function SkillSwitchPanel(props) {
|
|
236
513
|
var t = props.t;
|
|
237
514
|
var form = props.actions.form;
|
|
238
|
-
var state = props.useSwitches(function (value) { return value; });
|
|
239
515
|
var hostActive = props.useLocaleActive(function (v) { return v && v.preference === 'en' ? 'en' : 'zh'; });
|
|
516
|
+
var allNames = SKILL_CATALOG.map(function (skill) { return skill.name; });
|
|
517
|
+
|
|
518
|
+
var modelRef = React.useRef(null);
|
|
519
|
+
if (!modelRef.current) {
|
|
520
|
+
modelRef.current = new SwitchPanelModel(form, { t: t, allNames: allNames });
|
|
521
|
+
} else {
|
|
522
|
+
modelRef.current.updateScope(form);
|
|
523
|
+
}
|
|
240
524
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
var
|
|
248
|
-
|
|
249
|
-
|
|
525
|
+
React.useEffect(() => {
|
|
526
|
+
return () => {
|
|
527
|
+
if (modelRef.current) modelRef.current.dispose();
|
|
528
|
+
};
|
|
529
|
+
}, []);
|
|
530
|
+
|
|
531
|
+
var state = React.useSyncExternalStore(
|
|
532
|
+
(listener) => modelRef.current.subscribe(listener),
|
|
533
|
+
() => modelRef.current.getSnapshot()
|
|
534
|
+
);
|
|
535
|
+
var controller = modelRef.current;
|
|
250
536
|
|
|
251
537
|
if (state.status !== 'ready') {
|
|
252
538
|
return h('div', { className: 'spSw' },
|
|
@@ -254,62 +540,27 @@ window.__ModuleLoader__.load({
|
|
|
254
540
|
h('p', { className: 'spSwIntro' }, t('hostUnavailable')));
|
|
255
541
|
}
|
|
256
542
|
|
|
257
|
-
var
|
|
258
|
-
var
|
|
259
|
-
var
|
|
260
|
-
var
|
|
261
|
-
? rawDisabled
|
|
262
|
-
: Object.assign({}, value.modelDisabled || {}, value.userDisabled || {});
|
|
263
|
-
var language = readLanguage(value);
|
|
264
|
-
var langConfigured = language !== undefined;
|
|
265
|
-
var langValue = langConfigured ? language : 'auto';
|
|
543
|
+
var disabled = state.disabled;
|
|
544
|
+
var language = state.language;
|
|
545
|
+
var langConfigured = state.langConfigured;
|
|
546
|
+
var langValue = state.langValue;
|
|
266
547
|
var langOptions = [
|
|
267
548
|
{ value: 'zh', label: t('langZh') },
|
|
268
549
|
{ value: 'en', label: t('langEn') },
|
|
269
550
|
{ value: 'auto', label: t('langAuto') },
|
|
270
551
|
];
|
|
271
|
-
var
|
|
272
|
-
if (next === 'auto') {
|
|
273
|
-
submit(form, t, ['language'], 'enable', setPending, setFailures,
|
|
274
|
-
[{ op: 'unset', path: [LANGUAGE_FIELD] }]);
|
|
275
|
-
} else {
|
|
276
|
-
submit(form, t, ['language'], 'enable', setPending, setFailures,
|
|
277
|
-
[{ op: 'set', path: [LANGUAGE_FIELD], value: next }]);
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
var writable = state.writable !== false && state.mode !== 'memory';
|
|
281
|
-
|
|
282
|
-
var lower = keyword.trim().toLowerCase();
|
|
283
|
-
/* 描述取词:按当前语言偏好取对应语言文本,两侧都参与搜索过滤。 */
|
|
284
|
-
var skillText = function (skill) {
|
|
285
|
-
var effective = language === undefined ? hostActive : language;
|
|
286
|
-
return effective === 'en' && skill.descriptionEn ? skill.descriptionEn : skill.description;
|
|
287
|
-
};
|
|
288
|
-
var shown = lower === ''
|
|
289
|
-
? SKILL_CATALOG
|
|
290
|
-
: SKILL_CATALOG.filter(function (skill) {
|
|
291
|
-
var name = skill.name.toLowerCase();
|
|
292
|
-
return name.indexOf(lower) >= 0
|
|
293
|
-
|| skill.description.toLowerCase().indexOf(lower) >= 0
|
|
294
|
-
|| (skill.descriptionEn || '').toLowerCase().indexOf(lower) >= 0;
|
|
295
|
-
});
|
|
552
|
+
var writable = state.writable;
|
|
296
553
|
|
|
297
|
-
var
|
|
298
|
-
var batchEnable = function () {
|
|
299
|
-
submit(form, t, allNames, 'enable', setPending, setFailures);
|
|
300
|
-
};
|
|
301
|
-
var batchDisable = function () {
|
|
302
|
-
submit(form, t, allNames, 'disable', setPending, setFailures);
|
|
303
|
-
};
|
|
554
|
+
var shown = controller.getVisibleSkills(hostActive);
|
|
304
555
|
|
|
305
556
|
var rows = shown.map(function (skill) {
|
|
306
|
-
var busy = !!pending[skill.name] || !writable;
|
|
307
|
-
var failure = failures[skill.name];
|
|
557
|
+
var busy = !!state.pending[skill.name] || !writable;
|
|
558
|
+
var failure = state.failures[skill.name];
|
|
308
559
|
var on = !isBlocked(disabled, skill.name);
|
|
309
560
|
return h('li', { key: skill.name, className: 'spSwItem' },
|
|
310
561
|
h('div', { className: 'spSwMain' },
|
|
311
562
|
h('div', { className: 'spSwName' }, skill.name),
|
|
312
|
-
h('p', { className: 'spSwDesc' },
|
|
563
|
+
h('p', { className: 'spSwDesc' }, skill.displayText),
|
|
313
564
|
failure ? h('p', { className: 'spSwErr', role: 'alert' }, failure) : null),
|
|
314
565
|
h('div', { className: 'spSwSwitch' },
|
|
315
566
|
h('span', { className: 'spSwSwitchLabel' }, t('invocable')),
|
|
@@ -319,7 +570,7 @@ window.__ModuleLoader__.load({
|
|
|
319
570
|
label: t('invocable') + ' ' + skill.name,
|
|
320
571
|
title: t('invocableHint'),
|
|
321
572
|
onChange: function (next) {
|
|
322
|
-
|
|
573
|
+
controller.toggle(skill.name, next);
|
|
323
574
|
},
|
|
324
575
|
})));
|
|
325
576
|
});
|
|
@@ -334,13 +585,13 @@ window.__ModuleLoader__.load({
|
|
|
334
585
|
label: t('langTitle'),
|
|
335
586
|
value: langValue,
|
|
336
587
|
options: langOptions,
|
|
337
|
-
disabled: !writable || !!pending['language'],
|
|
338
|
-
onChange:
|
|
588
|
+
disabled: !writable || !!state.pending['language'],
|
|
589
|
+
onChange: function (next) { controller.setLanguage(next); },
|
|
339
590
|
}),
|
|
340
591
|
!langConfigured
|
|
341
592
|
? h('p', { className: 'spSwLangNote' }, t('langUnsetHint', { lang: t(hostActive === 'en' ? 'langEn' : 'langZh') }))
|
|
342
593
|
: h('p', { className: 'spSwLangNote' }, t('langNote')),
|
|
343
|
-
failures['language'] ? h('span', { className: 'spSwLangFailure', role: 'alert' }, failures['language']) : null),
|
|
594
|
+
state.failures['language'] ? h('span', { className: 'spSwLangFailure', role: 'alert' }, state.failures['language']) : null),
|
|
344
595
|
|
|
345
596
|
h('div', { className: 'spSwBar' },
|
|
346
597
|
h(P.Button, {
|
|
@@ -348,29 +599,29 @@ window.__ModuleLoader__.load({
|
|
|
348
599
|
size: 'sm',
|
|
349
600
|
disabled: !writable,
|
|
350
601
|
title: t('resetHint'),
|
|
351
|
-
onClick:
|
|
602
|
+
onClick: function () { controller.enableAll(); },
|
|
352
603
|
}, t('enableAll')),
|
|
353
604
|
h(P.Button, {
|
|
354
605
|
variant: 'outline',
|
|
355
606
|
size: 'sm',
|
|
356
607
|
disabled: !writable,
|
|
357
608
|
title: t('disableAllHint'),
|
|
358
|
-
onClick:
|
|
609
|
+
onClick: function () { controller.disableAll(); },
|
|
359
610
|
}, t('disableAll')),
|
|
360
611
|
h(P.Button, {
|
|
361
612
|
variant: 'ghost',
|
|
362
613
|
size: 'sm',
|
|
363
614
|
disabled: !writable,
|
|
364
615
|
title: t('resetHint'),
|
|
365
|
-
onClick:
|
|
616
|
+
onClick: function () { controller.resetAll(); },
|
|
366
617
|
}, t('resetAll')),
|
|
367
618
|
h(P.Input, {
|
|
368
619
|
className: 'spSwSearch',
|
|
369
620
|
type: 'search',
|
|
370
|
-
value: keyword,
|
|
621
|
+
value: state.keyword,
|
|
371
622
|
placeholder: t('search'),
|
|
372
623
|
'aria-label': t('search'),
|
|
373
|
-
onChange: function (event) { setKeyword(event.target.value); },
|
|
624
|
+
onChange: function (event) { controller.setKeyword(event.target.value); },
|
|
374
625
|
})),
|
|
375
626
|
shown.length === 0
|
|
376
627
|
? h('p', { className: 'spSwEmpty' }, t('empty'))
|
|
@@ -421,6 +672,8 @@ window.__ModuleLoader__.load({
|
|
|
421
672
|
|
|
422
673
|
exports.apply = apply;
|
|
423
674
|
exports.inject = ['slots', 'configForms', 'locale'];
|
|
675
|
+
exports.SwitchPanelModel = SwitchPanelModel;
|
|
676
|
+
exports.SKILL_CATALOG = SKILL_CATALOG;
|
|
424
677
|
return module.exports;
|
|
425
678
|
},
|
|
426
679
|
});
|
package/lib/superpowers.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { SkillCatalog } from './catalog.js';
|
|
|
11
11
|
import { SkillDocument } from './document.js';
|
|
12
12
|
export { SkillCatalog, EXPECTED_SKILL_COUNT, type SpecificationReport } from './catalog.js';
|
|
13
13
|
export { SkillDocument, type SpecificationTestResult } from './document.js';
|
|
14
|
-
export { SkillSwitches, applySwitches, readSwitches } from './switches.js';
|
|
14
|
+
export { SkillSwitches, applySwitches, extractCleanDisabled, extractCleanLanguage, extractCleanSwitches, isConfigCorrupted, readSwitches, type CleanSwitchesExtraction, } from './switches.js';
|
|
15
15
|
declare module '@deepseek-ai/cordis' {
|
|
16
16
|
interface Events {
|
|
17
17
|
/**
|
package/lib/superpowers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"superpowers.d.ts","sourceRoot":"","sources":["../src/superpowers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAQ5D,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"superpowers.d.ts","sourceRoot":"","sources":["../src/superpowers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAQ5D,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAS7C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC3F,OAAO,EAAE,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EACL,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAA;AAQtB,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd;;;;WAIG;QACH,wBAAwB,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;QACrE;;;WAGG;QACH,wBAAwB,IAAI,IAAI,CAAA;KACjC;CACF;AAMD,eAAO,MAAM,MAAM,EAyC0C,MAAM,CAAC,MAAM,CAAC,CAAA;AAE3E,MAAM,WAAW,MAAM;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wDAAwD;IACxD,QAAQ,EAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IAC3C,2CAA2C;IAC3C,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC3C,wCAAwC;IACxC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAChD,kCAAkC;IAClC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAChD;AAMD,eAAO,MAAM,IAAI,gBAAgB,CAAA;AACjC,eAAO,MAAM,MAAM,qBAAsB,CAAA;AA4GzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA6CxD;;;;;;;;;AAED,wBAA2E"}
|