@lmzhen/dsh-evolution-settings-ui 0.22.0 → 0.24.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/lib/client.js +361 -152
- package/lib/types/client/ParamCard.d.ts +19 -7
- package/lib/types/client/PendingCard.d.ts +14 -1
- package/lib/types/client/RowConfigCard.d.ts +1 -1
- package/lib/types/client/generated-about.d.ts +11 -0
- package/lib/types/client/generated-params.d.ts +2 -0
- package/lib/types/client/guards.d.ts +13 -0
- package/lib/types/client/messages.d.ts +31 -4
- package/lib/types/client/seam.d.ts +4 -0
- package/lib/types/client/source.d.ts +4 -8
- package/package.json +1 -1
- package/lib/types/client/settle.d.ts +0 -35
package/lib/client.js
CHANGED
|
@@ -47,7 +47,7 @@ window.__ModuleLoader__.load({
|
|
|
47
47
|
};
|
|
48
48
|
return {
|
|
49
49
|
ok: false,
|
|
50
|
-
message: typeof body.message === "string" && body.message !== "" ? body.message : "
|
|
50
|
+
message: typeof body.message === "string" && body.message !== "" ? body.message : "宿主拒绝了该请求"
|
|
51
51
|
};
|
|
52
52
|
} catch (error) {
|
|
53
53
|
return {
|
|
@@ -89,7 +89,27 @@ window.__ModuleLoader__.load({
|
|
|
89
89
|
control: "number",
|
|
90
90
|
unit: "毫秒",
|
|
91
91
|
values: [],
|
|
92
|
-
valueLabels: []
|
|
92
|
+
valueLabels: [],
|
|
93
|
+
atLeast: ""
|
|
94
|
+
}, {
|
|
95
|
+
id: "approvalConfirm",
|
|
96
|
+
group: "write-caps",
|
|
97
|
+
doc: "What the confirmation before an APPROVE does: write straight through, ask first, or treat an unanswered prompt as a cancel. The same three words skillWriteConfirm uses for a skill write.",
|
|
98
|
+
label: "批准前先确认",
|
|
99
|
+
hint: "点「批准」时要不要再确认一次:直接执行 / 先确认 / 等待超时即取消。默认直接执行(不打断批量批准)。",
|
|
100
|
+
control: "select",
|
|
101
|
+
unit: "",
|
|
102
|
+
values: [
|
|
103
|
+
"auto",
|
|
104
|
+
"ask",
|
|
105
|
+
"timeout"
|
|
106
|
+
],
|
|
107
|
+
valueLabels: [
|
|
108
|
+
"直接执行",
|
|
109
|
+
"先确认",
|
|
110
|
+
"等待超时即取消"
|
|
111
|
+
],
|
|
112
|
+
atLeast: ""
|
|
93
113
|
}]
|
|
94
114
|
},
|
|
95
115
|
{
|
|
@@ -104,7 +124,8 @@ window.__ModuleLoader__.load({
|
|
|
104
124
|
control: "switch",
|
|
105
125
|
unit: "",
|
|
106
126
|
values: [],
|
|
107
|
-
valueLabels: []
|
|
127
|
+
valueLabels: [],
|
|
128
|
+
atLeast: ""
|
|
108
129
|
}]
|
|
109
130
|
},
|
|
110
131
|
{
|
|
@@ -120,7 +141,8 @@ window.__ModuleLoader__.load({
|
|
|
120
141
|
control: "number",
|
|
121
142
|
unit: "小时",
|
|
122
143
|
values: [],
|
|
123
|
-
valueLabels: []
|
|
144
|
+
valueLabels: [],
|
|
145
|
+
atLeast: ""
|
|
124
146
|
},
|
|
125
147
|
{
|
|
126
148
|
id: "staleAfterDays",
|
|
@@ -131,7 +153,8 @@ window.__ModuleLoader__.load({
|
|
|
131
153
|
control: "number",
|
|
132
154
|
unit: "天",
|
|
133
155
|
values: [],
|
|
134
|
-
valueLabels: []
|
|
156
|
+
valueLabels: [],
|
|
157
|
+
atLeast: ""
|
|
135
158
|
},
|
|
136
159
|
{
|
|
137
160
|
id: "archiveAfterDays",
|
|
@@ -142,7 +165,8 @@ window.__ModuleLoader__.load({
|
|
|
142
165
|
control: "number",
|
|
143
166
|
unit: "天",
|
|
144
167
|
values: [],
|
|
145
|
-
valueLabels: []
|
|
168
|
+
valueLabels: [],
|
|
169
|
+
atLeast: "staleAfterDays"
|
|
146
170
|
},
|
|
147
171
|
{
|
|
148
172
|
id: "minIdleHours",
|
|
@@ -153,7 +177,8 @@ window.__ModuleLoader__.load({
|
|
|
153
177
|
control: "number",
|
|
154
178
|
unit: "小时",
|
|
155
179
|
values: [],
|
|
156
|
-
valueLabels: []
|
|
180
|
+
valueLabels: [],
|
|
181
|
+
atLeast: ""
|
|
157
182
|
},
|
|
158
183
|
{
|
|
159
184
|
id: "minIdleFailOpen",
|
|
@@ -164,7 +189,8 @@ window.__ModuleLoader__.load({
|
|
|
164
189
|
control: "switch",
|
|
165
190
|
unit: "",
|
|
166
191
|
values: [],
|
|
167
|
-
valueLabels: []
|
|
192
|
+
valueLabels: [],
|
|
193
|
+
atLeast: ""
|
|
168
194
|
},
|
|
169
195
|
{
|
|
170
196
|
id: "llmReview",
|
|
@@ -175,7 +201,8 @@ window.__ModuleLoader__.load({
|
|
|
175
201
|
control: "switch",
|
|
176
202
|
unit: "",
|
|
177
203
|
values: [],
|
|
178
|
-
valueLabels: []
|
|
204
|
+
valueLabels: [],
|
|
205
|
+
atLeast: ""
|
|
179
206
|
},
|
|
180
207
|
{
|
|
181
208
|
id: "curatorReviewMaxTokens",
|
|
@@ -186,7 +213,8 @@ window.__ModuleLoader__.load({
|
|
|
186
213
|
control: "number",
|
|
187
214
|
unit: "token",
|
|
188
215
|
values: [],
|
|
189
|
-
valueLabels: []
|
|
216
|
+
valueLabels: [],
|
|
217
|
+
atLeast: ""
|
|
190
218
|
},
|
|
191
219
|
{
|
|
192
220
|
id: "curatorReviewTimeoutMs",
|
|
@@ -197,7 +225,8 @@ window.__ModuleLoader__.load({
|
|
|
197
225
|
control: "number",
|
|
198
226
|
unit: "毫秒",
|
|
199
227
|
values: [],
|
|
200
|
-
valueLabels: []
|
|
228
|
+
valueLabels: [],
|
|
229
|
+
atLeast: ""
|
|
201
230
|
},
|
|
202
231
|
{
|
|
203
232
|
id: "healthSoftBodyChars",
|
|
@@ -208,7 +237,8 @@ window.__ModuleLoader__.load({
|
|
|
208
237
|
control: "number",
|
|
209
238
|
unit: "字符",
|
|
210
239
|
values: [],
|
|
211
|
-
valueLabels: []
|
|
240
|
+
valueLabels: [],
|
|
241
|
+
atLeast: ""
|
|
212
242
|
},
|
|
213
243
|
{
|
|
214
244
|
id: "healthStampDensityPerKb",
|
|
@@ -219,7 +249,8 @@ window.__ModuleLoader__.load({
|
|
|
219
249
|
control: "number",
|
|
220
250
|
unit: "处/KB",
|
|
221
251
|
values: [],
|
|
222
|
-
valueLabels: []
|
|
252
|
+
valueLabels: [],
|
|
253
|
+
atLeast: ""
|
|
223
254
|
},
|
|
224
255
|
{
|
|
225
256
|
id: "healthChurnMinPatches",
|
|
@@ -230,7 +261,8 @@ window.__ModuleLoader__.load({
|
|
|
230
261
|
control: "number",
|
|
231
262
|
unit: "处",
|
|
232
263
|
values: [],
|
|
233
|
-
valueLabels: []
|
|
264
|
+
valueLabels: [],
|
|
265
|
+
atLeast: ""
|
|
234
266
|
}
|
|
235
267
|
]
|
|
236
268
|
},
|
|
@@ -247,7 +279,8 @@ window.__ModuleLoader__.load({
|
|
|
247
279
|
control: "number",
|
|
248
280
|
unit: "次",
|
|
249
281
|
values: [],
|
|
250
|
-
valueLabels: []
|
|
282
|
+
valueLabels: [],
|
|
283
|
+
atLeast: ""
|
|
251
284
|
},
|
|
252
285
|
{
|
|
253
286
|
id: "reviewMemoryInterval",
|
|
@@ -258,7 +291,8 @@ window.__ModuleLoader__.load({
|
|
|
258
291
|
control: "number",
|
|
259
292
|
unit: "次",
|
|
260
293
|
values: [],
|
|
261
|
-
valueLabels: []
|
|
294
|
+
valueLabels: [],
|
|
295
|
+
atLeast: ""
|
|
262
296
|
},
|
|
263
297
|
{
|
|
264
298
|
id: "skillReviewTrigger",
|
|
@@ -277,7 +311,8 @@ window.__ModuleLoader__.load({
|
|
|
277
311
|
"按间隔",
|
|
278
312
|
"按任务完成",
|
|
279
313
|
"两者"
|
|
280
|
-
]
|
|
314
|
+
],
|
|
315
|
+
atLeast: ""
|
|
281
316
|
},
|
|
282
317
|
{
|
|
283
318
|
id: "skillReviewCompletionMinToolCalls",
|
|
@@ -288,7 +323,8 @@ window.__ModuleLoader__.load({
|
|
|
288
323
|
control: "number",
|
|
289
324
|
unit: "次",
|
|
290
325
|
values: [],
|
|
291
|
-
valueLabels: []
|
|
326
|
+
valueLabels: [],
|
|
327
|
+
atLeast: ""
|
|
292
328
|
},
|
|
293
329
|
{
|
|
294
330
|
id: "reviewEnabled",
|
|
@@ -299,7 +335,8 @@ window.__ModuleLoader__.load({
|
|
|
299
335
|
control: "switch",
|
|
300
336
|
unit: "",
|
|
301
337
|
values: [],
|
|
302
|
-
valueLabels: []
|
|
338
|
+
valueLabels: [],
|
|
339
|
+
atLeast: ""
|
|
303
340
|
},
|
|
304
341
|
{
|
|
305
342
|
id: "reviewMode",
|
|
@@ -310,7 +347,8 @@ window.__ModuleLoader__.load({
|
|
|
310
347
|
control: "select",
|
|
311
348
|
unit: "",
|
|
312
349
|
values: ["subagent", "inject"],
|
|
313
|
-
valueLabels: ["交给子代理", "在当前会话里"]
|
|
350
|
+
valueLabels: ["交给子代理", "在当前会话里"],
|
|
351
|
+
atLeast: ""
|
|
314
352
|
},
|
|
315
353
|
{
|
|
316
354
|
id: "reviewWakeInject",
|
|
@@ -321,7 +359,8 @@ window.__ModuleLoader__.load({
|
|
|
321
359
|
control: "switch",
|
|
322
360
|
unit: "",
|
|
323
361
|
values: [],
|
|
324
|
-
valueLabels: []
|
|
362
|
+
valueLabels: [],
|
|
363
|
+
atLeast: ""
|
|
325
364
|
}
|
|
326
365
|
]
|
|
327
366
|
},
|
|
@@ -338,7 +377,8 @@ window.__ModuleLoader__.load({
|
|
|
338
377
|
control: "number",
|
|
339
378
|
unit: "字符",
|
|
340
379
|
values: [],
|
|
341
|
-
valueLabels: []
|
|
380
|
+
valueLabels: [],
|
|
381
|
+
atLeast: ""
|
|
342
382
|
},
|
|
343
383
|
{
|
|
344
384
|
id: "userChars",
|
|
@@ -349,7 +389,8 @@ window.__ModuleLoader__.load({
|
|
|
349
389
|
control: "number",
|
|
350
390
|
unit: "字符",
|
|
351
391
|
values: [],
|
|
352
|
-
valueLabels: []
|
|
392
|
+
valueLabels: [],
|
|
393
|
+
atLeast: ""
|
|
353
394
|
},
|
|
354
395
|
{
|
|
355
396
|
id: "addDatePrefix",
|
|
@@ -360,7 +401,8 @@ window.__ModuleLoader__.load({
|
|
|
360
401
|
control: "switch",
|
|
361
402
|
unit: "",
|
|
362
403
|
values: [],
|
|
363
|
-
valueLabels: []
|
|
404
|
+
valueLabels: [],
|
|
405
|
+
atLeast: ""
|
|
364
406
|
},
|
|
365
407
|
{
|
|
366
408
|
id: "maxConsolidationFailures",
|
|
@@ -371,7 +413,8 @@ window.__ModuleLoader__.load({
|
|
|
371
413
|
control: "number",
|
|
372
414
|
unit: "次",
|
|
373
415
|
values: [],
|
|
374
|
-
valueLabels: []
|
|
416
|
+
valueLabels: [],
|
|
417
|
+
atLeast: ""
|
|
375
418
|
}
|
|
376
419
|
]
|
|
377
420
|
},
|
|
@@ -387,7 +430,8 @@ window.__ModuleLoader__.load({
|
|
|
387
430
|
control: "number",
|
|
388
431
|
unit: "字符",
|
|
389
432
|
values: [],
|
|
390
|
-
valueLabels: []
|
|
433
|
+
valueLabels: [],
|
|
434
|
+
atLeast: ""
|
|
391
435
|
}]
|
|
392
436
|
},
|
|
393
437
|
{
|
|
@@ -403,7 +447,8 @@ window.__ModuleLoader__.load({
|
|
|
403
447
|
control: "number",
|
|
404
448
|
unit: "字符",
|
|
405
449
|
values: [],
|
|
406
|
-
valueLabels: []
|
|
450
|
+
valueLabels: [],
|
|
451
|
+
atLeast: ""
|
|
407
452
|
},
|
|
408
453
|
{
|
|
409
454
|
id: "maxSkillFileBytes",
|
|
@@ -414,7 +459,8 @@ window.__ModuleLoader__.load({
|
|
|
414
459
|
control: "number",
|
|
415
460
|
unit: "字节",
|
|
416
461
|
values: [],
|
|
417
|
-
valueLabels: []
|
|
462
|
+
valueLabels: [],
|
|
463
|
+
atLeast: ""
|
|
418
464
|
},
|
|
419
465
|
{
|
|
420
466
|
id: "maxSkillNameLength",
|
|
@@ -425,7 +471,8 @@ window.__ModuleLoader__.load({
|
|
|
425
471
|
control: "number",
|
|
426
472
|
unit: "字符",
|
|
427
473
|
values: [],
|
|
428
|
-
valueLabels: []
|
|
474
|
+
valueLabels: [],
|
|
475
|
+
atLeast: ""
|
|
429
476
|
},
|
|
430
477
|
{
|
|
431
478
|
id: "maxDescriptionLength",
|
|
@@ -436,7 +483,8 @@ window.__ModuleLoader__.load({
|
|
|
436
483
|
control: "number",
|
|
437
484
|
unit: "字符",
|
|
438
485
|
values: [],
|
|
439
|
-
valueLabels: []
|
|
486
|
+
valueLabels: [],
|
|
487
|
+
atLeast: ""
|
|
440
488
|
},
|
|
441
489
|
{
|
|
442
490
|
id: "descriptionStrict",
|
|
@@ -447,7 +495,8 @@ window.__ModuleLoader__.load({
|
|
|
447
495
|
control: "switch",
|
|
448
496
|
unit: "",
|
|
449
497
|
values: [],
|
|
450
|
-
valueLabels: []
|
|
498
|
+
valueLabels: [],
|
|
499
|
+
atLeast: ""
|
|
451
500
|
},
|
|
452
501
|
{
|
|
453
502
|
id: "strictCrossSource",
|
|
@@ -458,7 +507,8 @@ window.__ModuleLoader__.load({
|
|
|
458
507
|
control: "switch",
|
|
459
508
|
unit: "",
|
|
460
509
|
values: [],
|
|
461
|
-
valueLabels: []
|
|
510
|
+
valueLabels: [],
|
|
511
|
+
atLeast: ""
|
|
462
512
|
},
|
|
463
513
|
{
|
|
464
514
|
id: "citationPolicy",
|
|
@@ -469,7 +519,8 @@ window.__ModuleLoader__.load({
|
|
|
469
519
|
control: "select",
|
|
470
520
|
unit: "",
|
|
471
521
|
values: ["verify", "refuse"],
|
|
472
|
-
valueLabels: ["先检查", "直接拒绝"]
|
|
522
|
+
valueLabels: ["先检查", "直接拒绝"],
|
|
523
|
+
atLeast: ""
|
|
473
524
|
},
|
|
474
525
|
{
|
|
475
526
|
id: "supportFileCharPolicy",
|
|
@@ -480,7 +531,8 @@ window.__ModuleLoader__.load({
|
|
|
480
531
|
control: "select",
|
|
481
532
|
unit: "",
|
|
482
533
|
values: ["report", "enforce"],
|
|
483
|
-
valueLabels: ["只提醒", "拒绝写入"]
|
|
534
|
+
valueLabels: ["只提醒", "拒绝写入"],
|
|
535
|
+
atLeast: ""
|
|
484
536
|
},
|
|
485
537
|
{
|
|
486
538
|
id: "skillWriteConfirm",
|
|
@@ -499,7 +551,8 @@ window.__ModuleLoader__.load({
|
|
|
499
551
|
"不弹窗直接写入",
|
|
500
552
|
"一直等待回答",
|
|
501
553
|
"超时自动取消"
|
|
502
|
-
]
|
|
554
|
+
],
|
|
555
|
+
atLeast: ""
|
|
503
556
|
},
|
|
504
557
|
{
|
|
505
558
|
id: "skillWriteConfirmTimeoutSeconds",
|
|
@@ -510,7 +563,8 @@ window.__ModuleLoader__.load({
|
|
|
510
563
|
control: "number",
|
|
511
564
|
unit: "秒",
|
|
512
565
|
values: [],
|
|
513
|
-
valueLabels: []
|
|
566
|
+
valueLabels: [],
|
|
567
|
+
atLeast: ""
|
|
514
568
|
}
|
|
515
569
|
]
|
|
516
570
|
}
|
|
@@ -655,6 +709,17 @@ window.__ModuleLoader__.load({
|
|
|
655
709
|
* refusal is shown with the host's own sentence.
|
|
656
710
|
* @module @lmzhen/dsh-evolution-settings-ui/client/PendingCard
|
|
657
711
|
*/
|
|
712
|
+
/**
|
|
713
|
+
* U-6: the registry's gate word, read out of a section's user layer. ONE definition, exported so the
|
|
714
|
+
* mapping itself is judgeable: the entry does the wiring, this does the reading. Anything that is not
|
|
715
|
+
* one of the two explicit words falls back to the shipped default (`auto`) — a document written by a
|
|
716
|
+
* future version must not silently turn the confirmation ON, and a typo must not turn it off. The
|
|
717
|
+
* independent review flagged that this reader had no case at all (P2-11).
|
|
718
|
+
*/
|
|
719
|
+
function confirmModeFrom(user) {
|
|
720
|
+
const value = typeof user === "object" && user !== null ? user.approvalConfirm : void 0;
|
|
721
|
+
return value === "ask" || value === "timeout" ? value : "auto";
|
|
722
|
+
}
|
|
658
723
|
/** Which word one age bucket gets; an unknown bucket falls back to the count form. */
|
|
659
724
|
const AGE_KEYS = Object.freeze({
|
|
660
725
|
now: "approvalAgeNow",
|
|
@@ -676,6 +741,8 @@ window.__ModuleLoader__.load({
|
|
|
676
741
|
*/
|
|
677
742
|
function PendingCard(props) {
|
|
678
743
|
const { t, api } = props;
|
|
744
|
+
const confirmMode = props.confirmMode?.() ?? "auto";
|
|
745
|
+
const [armed, setArmed] = (0, react.useState)(null);
|
|
679
746
|
const [state, setState] = (0, react.useState)(INITIAL_PENDING_STATE);
|
|
680
747
|
const [open, setOpen] = (0, react.useState)(true);
|
|
681
748
|
const latest = (0, react.useRef)(state);
|
|
@@ -731,7 +798,7 @@ window.__ModuleLoader__.load({
|
|
|
731
798
|
const age = (row) => {
|
|
732
799
|
const key = AGE_KEYS[row.age.unit];
|
|
733
800
|
if (key === void 0) return String(row.age.n);
|
|
734
|
-
return t(key
|
|
801
|
+
return t(key, { n: row.age.n });
|
|
735
802
|
};
|
|
736
803
|
/** Ask the host what this record would store; the answer lands only if the row is still open. */
|
|
737
804
|
const loadPreview = async (id) => {
|
|
@@ -758,18 +825,27 @@ window.__ModuleLoader__.load({
|
|
|
758
825
|
};
|
|
759
826
|
/** The facts line, then the source view: the same shape the history panel's diff uses. */
|
|
760
827
|
const preview = (view) => {
|
|
761
|
-
if (view.kind === "loading") return (0, react.createElement)("p", {
|
|
762
|
-
|
|
763
|
-
|
|
828
|
+
if (view.kind === "loading") return (0, react.createElement)("p", {
|
|
829
|
+
className: "evolution-param-note",
|
|
830
|
+
role: "status"
|
|
831
|
+
}, t("approvalPreviewReading"));
|
|
832
|
+
if (view.kind === "failed") return (0, react.createElement)("p", {
|
|
833
|
+
className: "evolution-param-error",
|
|
834
|
+
role: "status"
|
|
835
|
+
}, view.message);
|
|
836
|
+
if (view.kind === "unavailable") return (0, react.createElement)("p", {
|
|
837
|
+
className: "evolution-param-error",
|
|
838
|
+
role: "status"
|
|
839
|
+
}, t("approvalPreviewNone") + view.reason);
|
|
764
840
|
const facts = [
|
|
765
841
|
(0, react.createElement)("span", {
|
|
766
842
|
className: "evolution-param-fact",
|
|
767
843
|
key: "added"
|
|
768
|
-
}, t("approvalDiffAdded"
|
|
844
|
+
}, t("approvalDiffAdded", { n: view.answer.linesAdded })),
|
|
769
845
|
(0, react.createElement)("span", {
|
|
770
846
|
className: "evolution-param-fact",
|
|
771
847
|
key: "removed"
|
|
772
|
-
}, t("approvalDiffRemoved"
|
|
848
|
+
}, t("approvalDiffRemoved", { n: view.answer.linesRemoved })),
|
|
773
849
|
...view.answer.truncated ? [(0, react.createElement)("span", {
|
|
774
850
|
className: "evolution-param-fact",
|
|
775
851
|
key: "cut"
|
|
@@ -798,38 +874,79 @@ window.__ModuleLoader__.load({
|
|
|
798
874
|
if (entry.status === "executing") return (0, react.createElement)("div", {
|
|
799
875
|
className: "evolution-param-field",
|
|
800
876
|
key: entry.id
|
|
801
|
-
}, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("span", { className: "evolution-param-source" }, t(KIND_KEYS[entry.kind])), (0, react.createElement)("span", { className: "evolution-param-value" }, entry.summary)), (0, react.createElement)("p", { className: "evolution-param-hint" }, age(entry)), (0, react.createElement)("p", {
|
|
877
|
+
}, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("span", { className: "evolution-param-source" }, t(KIND_KEYS[entry.kind])), (0, react.createElement)("span", { className: "evolution-param-value" }, entry.summary)), (0, react.createElement)("p", { className: "evolution-param-hint" }, age(entry)), (0, react.createElement)("p", {
|
|
878
|
+
className: "evolution-param-note",
|
|
879
|
+
role: "status"
|
|
880
|
+
}, t("approvalExecuting")), entry.claimedBy === void 0 ? null : (0, react.createElement)("p", { className: "evolution-param-hint" }, entry.claimedBy));
|
|
802
881
|
const busy = state.busy.includes(entry.id);
|
|
803
|
-
const button = (label, action) => (0, react.createElement)("button", {
|
|
882
|
+
const button = (label, action, tone) => (0, react.createElement)("button", {
|
|
804
883
|
className: "evolution-param-button",
|
|
805
884
|
type: "button",
|
|
806
885
|
disabled: busy,
|
|
886
|
+
...tone === "primary" ? { "data-primary": "true" } : { "data-tone": tone },
|
|
807
887
|
onClick: () => {
|
|
888
|
+
if (action === "approve" && confirmMode === "ask" && armed !== entry.id) {
|
|
889
|
+
setArmed(entry.id);
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
setArmed(null);
|
|
808
893
|
decide(entry.id, action);
|
|
809
894
|
}
|
|
810
895
|
}, busy ? t("approvalLoading") : t(label));
|
|
811
896
|
return (0, react.createElement)("div", {
|
|
812
897
|
className: "evolution-param-field",
|
|
813
898
|
key: entry.id
|
|
814
|
-
}, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("span", { className: "evolution-param-source" }, t(KIND_KEYS[entry.kind])), (0, react.createElement)("span", { className: "evolution-param-value" }, entry.summary)), (0, react.createElement)("p", { className: "evolution-param-hint" }, age(entry)),
|
|
899
|
+
}, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("span", { className: "evolution-param-source" }, t(KIND_KEYS[entry.kind])), (0, react.createElement)("span", { className: "evolution-param-value" }, entry.summary)), (0, react.createElement)("p", { className: "evolution-param-hint" }, age(entry)), armed === entry.id ? (0, react.createElement)("p", {
|
|
900
|
+
className: "evolution-param-note",
|
|
901
|
+
role: "status"
|
|
902
|
+
}, (0, react.createElement)("span", { className: "evolution-param-value" }, t("approvalConfirmNamed", { n: entry.summary })), (0, react.createElement)("button", {
|
|
903
|
+
className: "evolution-param-button",
|
|
904
|
+
type: "button",
|
|
905
|
+
"data-confirm": "yes",
|
|
906
|
+
"data-primary": "true",
|
|
907
|
+
onClick: () => {
|
|
908
|
+
setArmed(null);
|
|
909
|
+
decide(entry.id, "approve");
|
|
910
|
+
}
|
|
911
|
+
}, t("approvalConfirmYes")), (0, react.createElement)("button", {
|
|
912
|
+
className: "evolution-param-button",
|
|
913
|
+
type: "button",
|
|
914
|
+
"data-tone": "ghost",
|
|
915
|
+
onClick: () => {
|
|
916
|
+
setArmed(null);
|
|
917
|
+
}
|
|
918
|
+
}, t("approvalConfirmNo"))) : null, (0, react.createElement)("div", { className: "evolution-param-actions" }, button("approvalApprove", "approve", "primary"), button("approvalReject", "reject", "outline"), (0, react.createElement)("button", {
|
|
815
919
|
className: "evolution-param-button",
|
|
816
920
|
type: "button",
|
|
921
|
+
"data-tone": "ghost",
|
|
817
922
|
onClick: () => {
|
|
818
923
|
togglePreview(entry.id);
|
|
819
924
|
}
|
|
820
925
|
}, state.open === entry.id ? t("approvalPreviewClose") : t("approvalPreview"))), state.open === entry.id && state.preview !== null ? preview(state.preview) : null);
|
|
821
926
|
};
|
|
822
927
|
const body = () => {
|
|
823
|
-
if (state.view.kind === "loading") return (0, react.createElement)("p", {
|
|
824
|
-
|
|
825
|
-
|
|
928
|
+
if (state.view.kind === "loading") return (0, react.createElement)("p", {
|
|
929
|
+
className: "evolution-param-note",
|
|
930
|
+
role: "status"
|
|
931
|
+
}, t("approvalLoading"));
|
|
932
|
+
if (state.view.kind === "empty") return (0, react.createElement)("p", {
|
|
933
|
+
className: "evolution-param-note",
|
|
934
|
+
role: "status"
|
|
935
|
+
}, t("approvalEmpty"));
|
|
936
|
+
if (state.view.kind === "failed") return (0, react.createElement)("div", { className: "evolution-param-actions" }, (0, react.createElement)("p", {
|
|
937
|
+
className: "evolution-param-error",
|
|
938
|
+
role: "status"
|
|
939
|
+
}, t("approvalFailed") + ": " + state.view.message), (0, react.createElement)("button", {
|
|
826
940
|
className: "evolution-param-button",
|
|
827
941
|
type: "button",
|
|
828
942
|
onClick: () => {
|
|
829
943
|
load();
|
|
830
944
|
}
|
|
831
945
|
}, t("approvalRetry")));
|
|
832
|
-
return (0, react.createElement)("div", null, ...state.view.rows.map(row), state.notice === null ? null : (0, react.createElement)("p", {
|
|
946
|
+
return (0, react.createElement)("div", null, ...state.view.rows.map(row), state.notice === null ? null : (0, react.createElement)("p", {
|
|
947
|
+
className: "evolution-param-error",
|
|
948
|
+
role: "status"
|
|
949
|
+
}, state.notice));
|
|
833
950
|
};
|
|
834
951
|
const rows = state.view.kind === "ready" ? state.view.rows : [];
|
|
835
952
|
const waiting = rows.filter((entry) => entry.status !== "executing").length;
|
|
@@ -841,7 +958,7 @@ window.__ModuleLoader__.load({
|
|
|
841
958
|
setOpen(!open);
|
|
842
959
|
},
|
|
843
960
|
"aria-expanded": open
|
|
844
|
-
}, (0, react.createElement)("span", { className: "evolution-param-card-title" }, t("approvalTitle")), waiting === 0 ? null : (0, react.createElement)("span", { className: "evolution-param-count" }, t("approvalCount"
|
|
961
|
+
}, (0, react.createElement)("span", { className: "evolution-param-card-title" }, t("approvalTitle")), waiting === 0 ? null : (0, react.createElement)("span", { className: "evolution-param-count" }, t("approvalCount", { n: waiting })), running === 0 ? null : (0, react.createElement)("span", { className: "evolution-param-count" }, t("approvalRunningCount", { n: running })), (0, react.createElement)("span", { className: "evolution-param-chevron" }, open ? "▲" : "▼")), open ? (0, react.createElement)("div", { className: "evolution-param-body" }, (0, react.createElement)("div", { className: "evolution-param-actions" }, (0, react.createElement)("button", {
|
|
845
962
|
className: "evolution-param-button",
|
|
846
963
|
type: "button",
|
|
847
964
|
onClick: () => {
|
|
@@ -867,7 +984,7 @@ window.__ModuleLoader__.load({
|
|
|
867
984
|
const zh = {
|
|
868
985
|
title: "自进化",
|
|
869
986
|
subtitle: "待你决定的写入在最上面;下面按功能列出你能改的参数,没有列出的由安装时的配置决定。",
|
|
870
|
-
overridden: "
|
|
987
|
+
overridden: "已覆盖",
|
|
871
988
|
deployment: "默认",
|
|
872
989
|
loading: "正在读取设置…",
|
|
873
990
|
unavailable: "这个功能没有启动(对应的插件没有安装)",
|
|
@@ -877,12 +994,21 @@ window.__ModuleLoader__.load({
|
|
|
877
994
|
apply: "保存",
|
|
878
995
|
reset: "恢复默认值",
|
|
879
996
|
empty: "这里没有可改项",
|
|
880
|
-
changed: "{n}
|
|
997
|
+
changed: "{n} 项已覆盖",
|
|
881
998
|
discard: "放弃修改",
|
|
882
999
|
saving: "保存中…",
|
|
883
1000
|
resetting: "恢复中…",
|
|
884
|
-
|
|
885
|
-
|
|
1001
|
+
destHost: "保存去向:本机配置",
|
|
1002
|
+
invalidNumber: "需要一个数字",
|
|
1003
|
+
invalidSelect: "不在允许的取值里",
|
|
1004
|
+
invalidAtLeast: "不能小于同组的 {n}",
|
|
1005
|
+
approvalConfirmNamed: "即将批准:{n}",
|
|
1006
|
+
approvalConfirmYes: "确认批准",
|
|
1007
|
+
approvalConfirmNo: "取消",
|
|
1008
|
+
destMemory: "保存去向:仅本次会话",
|
|
1009
|
+
resetTo: "复位为 {value}",
|
|
1010
|
+
refused: "这个值没有被接受(界面上保持原样)。想看原因:在对话里让它说明。",
|
|
1011
|
+
resetRefused: "恢复默认值没有生效(这一行还是你的值)。想看原因:在对话里让它说明。",
|
|
886
1012
|
cardReview: "会话回顾",
|
|
887
1013
|
cardMemory: "长期记忆",
|
|
888
1014
|
cardToolMemory: "记忆写入",
|
|
@@ -921,7 +1047,7 @@ window.__ModuleLoader__.load({
|
|
|
921
1047
|
const en = {
|
|
922
1048
|
title: "Self-evolution",
|
|
923
1049
|
subtitle: "Writes waiting for your decision come first; the changeable parameters are listed by feature below, and anything not listed comes from the deployment configuration.",
|
|
924
|
-
overridden: "
|
|
1050
|
+
overridden: "Overridden",
|
|
925
1051
|
deployment: "default",
|
|
926
1052
|
loading: "reading settings…",
|
|
927
1053
|
unavailable: "this feature is not running (its plugin is not installed)",
|
|
@@ -931,12 +1057,21 @@ window.__ModuleLoader__.load({
|
|
|
931
1057
|
apply: "Save",
|
|
932
1058
|
reset: "Reset to default",
|
|
933
1059
|
empty: "nothing to change here",
|
|
934
|
-
changed: "{n}
|
|
1060
|
+
changed: "{n} overridden",
|
|
935
1061
|
discard: "Discard",
|
|
936
1062
|
saving: "Saving…",
|
|
937
1063
|
resetting: "Resetting…",
|
|
938
|
-
|
|
939
|
-
|
|
1064
|
+
destHost: "Saved to: this machine",
|
|
1065
|
+
invalidNumber: "Needs a number",
|
|
1066
|
+
invalidSelect: "Not one of the allowed values",
|
|
1067
|
+
invalidAtLeast: "must not be below {n}",
|
|
1068
|
+
approvalConfirmNamed: "About to approve: {n}",
|
|
1069
|
+
approvalConfirmYes: "Approve",
|
|
1070
|
+
approvalConfirmNo: "Cancel",
|
|
1071
|
+
destMemory: "Saved to: this session only",
|
|
1072
|
+
resetTo: "Restores {value}",
|
|
1073
|
+
refused: "The value was not accepted (the page keeps what you see). For the reason, ask in the conversation.",
|
|
1074
|
+
resetRefused: "The reset did not take (this row still holds your value). For the reason, ask in the conversation.",
|
|
940
1075
|
cardReview: "Session review",
|
|
941
1076
|
cardMemory: "Long-term memory",
|
|
942
1077
|
cardToolMemory: "Writing memory",
|
|
@@ -991,45 +1126,33 @@ window.__ModuleLoader__.load({
|
|
|
991
1126
|
* @param language - which dictionary to read; defaults to Chinese.
|
|
992
1127
|
* @returns the copy this bundle carries.
|
|
993
1128
|
*/
|
|
994
|
-
function message(key, language = "
|
|
1129
|
+
function message(key, language = "en") {
|
|
995
1130
|
return language === "zh" ? zh[key] : en[key];
|
|
996
1131
|
}
|
|
997
|
-
//#endregion
|
|
998
|
-
//#region src/client/settle.ts
|
|
999
1132
|
/**
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1003
|
-
* not
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
* which keeps `0` and `-0` equal exactly as the serialization comparison did.
|
|
1008
|
-
* @param a - one side of the comparison.
|
|
1009
|
-
* @param b - the other side.
|
|
1010
|
-
* @returns true when the two are the same value.
|
|
1133
|
+
* Fill one TEMPLATE's `{slot}` placeholders (G5 C4). The seat's translator takes the values, so the
|
|
1134
|
+
* rule lives here instead of at every call site — `t('changed').replace('{n}', …)` used to be
|
|
1135
|
+
* written seven times across three components. An UNKNOWN slot is left standing: a missing value
|
|
1136
|
+
* must not print "undefined" into the operator's UI.
|
|
1137
|
+
* @param template - the resolved copy, with `{slot}` placeholders.
|
|
1138
|
+
* @param values - substitutions keyed by the slot name inside the braces.
|
|
1139
|
+
* @returns the filled copy.
|
|
1011
1140
|
*/
|
|
1012
|
-
function
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
return a.every((item, index) => sameValue(item, b[index]));
|
|
1018
|
-
}
|
|
1019
|
-
const left = a;
|
|
1020
|
-
const right = b;
|
|
1021
|
-
const keys = Object.keys(left);
|
|
1022
|
-
return keys.length === Object.keys(right).length && keys.every((key) => Object.hasOwn(right, key) && sameValue(left[key], right[key]));
|
|
1141
|
+
function fill(template, values) {
|
|
1142
|
+
return template.replace(/\{(\w+)\}/g, (match, slot) => {
|
|
1143
|
+
const value = values[slot];
|
|
1144
|
+
return value === void 0 ? match : String(value);
|
|
1145
|
+
});
|
|
1023
1146
|
}
|
|
1147
|
+
//#endregion
|
|
1148
|
+
//#region src/client/guards.ts
|
|
1024
1149
|
/**
|
|
1025
|
-
*
|
|
1026
|
-
* @param
|
|
1027
|
-
* @
|
|
1028
|
-
* @returns true when each staged id now holds the requested value, or is gone after an `unset`.
|
|
1150
|
+
* Is this a non-null, non-array object (what JSON calls an object)?
|
|
1151
|
+
* @param value - the value to test.
|
|
1152
|
+
* @returns whether it is a plain object.
|
|
1029
1153
|
*/
|
|
1030
|
-
function
|
|
1031
|
-
|
|
1032
|
-
return pending.every((entry) => entry.op === "unset" ? !Object.hasOwn(section, entry.id) : sameValue(section[entry.id], entry.want));
|
|
1154
|
+
function isRecord(value) {
|
|
1155
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1033
1156
|
}
|
|
1034
1157
|
//#endregion
|
|
1035
1158
|
//#region src/client/ParamCard.ts
|
|
@@ -1074,17 +1197,62 @@ window.__ModuleLoader__.load({
|
|
|
1074
1197
|
return trimmed;
|
|
1075
1198
|
}
|
|
1076
1199
|
}
|
|
1077
|
-
/**
|
|
1078
|
-
|
|
1079
|
-
|
|
1200
|
+
/**
|
|
1201
|
+
* U-4: whether one field's CURRENT text is a value the Host can take. The controls constrain their own
|
|
1202
|
+
* domains (a number input sanitizes, a select only offers listed values), so the reachable case is a
|
|
1203
|
+
* value the registry no longer lists — carried in the user layer and re-staged by any other edit.
|
|
1204
|
+
* @param field - the generated field.
|
|
1205
|
+
* @param text - the text the control holds right now.
|
|
1206
|
+
* @param peer - U-4: the text the row this field declares `atLeast` against currently holds (absent
|
|
1207
|
+
* when the field declares no relation, or when that row is not on this card).
|
|
1208
|
+
* @returns the message key explaining the refusal, or null when the value is acceptable.
|
|
1209
|
+
*/
|
|
1210
|
+
function invalidReason(field, text, peer) {
|
|
1211
|
+
const trimmed = text.trim();
|
|
1212
|
+
if (trimmed === "") return null;
|
|
1213
|
+
if (field.control === "number") {
|
|
1214
|
+
if (!Number.isFinite(Number(trimmed))) return "invalidNumber";
|
|
1215
|
+
if (field.atLeast !== "" && peer !== void 0 && peer.trim() !== "" && Number.isFinite(Number(peer))) {
|
|
1216
|
+
if (Number(trimmed) < Number(peer)) return "invalidAtLeast";
|
|
1217
|
+
}
|
|
1218
|
+
return null;
|
|
1219
|
+
}
|
|
1220
|
+
if (field.control === "select") return field.values.includes(trimmed) ? null : "invalidSelect";
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* U-5: the value a reset would restore, spelled for a reader. Only primitives are shown: the seat's
|
|
1225
|
+
* `base` may be a nested object, and `[object Object]` is worse than saying nothing.
|
|
1226
|
+
* @param value - the seat's base value for one field.
|
|
1227
|
+
* @returns its display string, or null when it is not a primitive.
|
|
1228
|
+
*/
|
|
1229
|
+
function resetToOf(value) {
|
|
1230
|
+
if (value === null || value === void 0) return null;
|
|
1231
|
+
if (typeof value === "string") return value;
|
|
1232
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1233
|
+
return null;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* The DOM id a field's control, its label and its explanation node all share. ONE definition: the
|
|
1237
|
+
* three call sites used to spell the string out, and the third one (the explanation node) referred to
|
|
1238
|
+
* a local that only existed inside the control — a ReferenceError on every invalid value, which the
|
|
1239
|
+
* unit-level fixture could not see because it never rendered one (independent review, P1-1).
|
|
1240
|
+
*/
|
|
1241
|
+
function controlId(field) {
|
|
1242
|
+
return "evolution-param-" + field.id;
|
|
1080
1243
|
}
|
|
1081
1244
|
/** One field's control, typed from the registry. */
|
|
1082
1245
|
function FieldControl(props) {
|
|
1083
1246
|
const { field, text } = props;
|
|
1247
|
+
const id = controlId(field);
|
|
1084
1248
|
const common = {
|
|
1085
|
-
id
|
|
1249
|
+
id,
|
|
1086
1250
|
disabled: props.disabled,
|
|
1087
|
-
className: "evolution-param-input"
|
|
1251
|
+
className: "evolution-param-input",
|
|
1252
|
+
...props.invalid === null ? {} : {
|
|
1253
|
+
"aria-invalid": "true",
|
|
1254
|
+
"aria-describedby": id + "-invalid"
|
|
1255
|
+
}
|
|
1088
1256
|
};
|
|
1089
1257
|
if (field.control === "switch") return (0, react.createElement)("input", {
|
|
1090
1258
|
...common,
|
|
@@ -1122,17 +1290,21 @@ window.__ModuleLoader__.load({
|
|
|
1122
1290
|
function FieldBlock(props) {
|
|
1123
1291
|
const { field, t } = props;
|
|
1124
1292
|
const unit = field.unit === "" ? null : (0, react.createElement)("span", { className: "evolution-param-unit" }, "(" + field.unit + ")");
|
|
1125
|
-
return (0, react.createElement)("div", { className: "evolution-param-field" }, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("label", { htmlFor:
|
|
1293
|
+
return (0, react.createElement)("div", { className: "evolution-param-field" }, (0, react.createElement)("div", { className: "evolution-param-label" }, (0, react.createElement)("label", { htmlFor: controlId(field) }, field.label === "" ? field.id : field.label), unit, props.overridden ? (0, react.createElement)("span", {
|
|
1126
1294
|
className: "evolution-param-source",
|
|
1127
|
-
"data-user":
|
|
1128
|
-
},
|
|
1295
|
+
"data-user": "true"
|
|
1296
|
+
}, t("overridden")) : null), FieldControl(props), (0, react.createElement)("p", { className: "evolution-param-hint" }, field.hint === "" ? field.doc : field.hint), props.invalid === null ? null : (0, react.createElement)("p", {
|
|
1297
|
+
id: controlId(field) + "-invalid",
|
|
1298
|
+
className: "evolution-param-error",
|
|
1299
|
+
role: "status"
|
|
1300
|
+
}, t(props.invalid)), props.overridden ? (0, react.createElement)("div", { className: "evolution-param-actions" }, (0, react.createElement)("button", {
|
|
1129
1301
|
type: "button",
|
|
1130
1302
|
className: "evolution-param-button",
|
|
1131
1303
|
disabled: props.disabled || props.clearing,
|
|
1132
1304
|
onClick: () => {
|
|
1133
1305
|
props.onClear(field.id);
|
|
1134
1306
|
}
|
|
1135
|
-
}, props.clearing ? t("resetting") : t("reset"))) : null);
|
|
1307
|
+
}, props.clearing ? t("resetting") : t("reset")), props.resetTo === null ? null : (0, react.createElement)("span", { className: "evolution-param-hint" }, t("resetTo", { value: props.resetTo }))) : null);
|
|
1136
1308
|
}
|
|
1137
1309
|
/**
|
|
1138
1310
|
* Render one row's card body from a supplied snapshot.
|
|
@@ -1147,10 +1319,16 @@ window.__ModuleLoader__.load({
|
|
|
1147
1319
|
const [error, setError] = (0, react.useState)("");
|
|
1148
1320
|
const [pending, setPending] = (0, react.useState)(null);
|
|
1149
1321
|
const [clearing, setClearing] = (0, react.useState)(null);
|
|
1150
|
-
if (snapshot.status === "loading") return (0, react.createElement)("p", {
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1322
|
+
if (snapshot.status === "loading") return (0, react.createElement)("p", {
|
|
1323
|
+
className: "evolution-param-note",
|
|
1324
|
+
role: "status"
|
|
1325
|
+
}, t("loading"));
|
|
1326
|
+
if (snapshot.status === "unavailable") return (0, react.createElement)("p", {
|
|
1327
|
+
className: "evolution-param-note",
|
|
1328
|
+
role: "status"
|
|
1329
|
+
}, t(snapshot.reason === "seat-missing" ? "seatMissing" : snapshot.reason === "projection-failed" ? "projectionFailed" : "unavailable"));
|
|
1330
|
+
const user = isRecord(snapshot.user) ? snapshot.user : {};
|
|
1331
|
+
const value = isRecord(snapshot.value) ? snapshot.value : {};
|
|
1154
1332
|
const disabled = !snapshot.writable;
|
|
1155
1333
|
const locked = disabled || busy || clearing !== null;
|
|
1156
1334
|
const titleKey = NAMESPACE_TITLES[namespace];
|
|
@@ -1158,6 +1336,12 @@ window.__ModuleLoader__.load({
|
|
|
1158
1336
|
const changed = fields.filter((field) => Object.hasOwn(user, field.id)).length;
|
|
1159
1337
|
const textOf = (field) => draft[field.id] ?? format(value[field.id]);
|
|
1160
1338
|
const dirty = fields.filter((field) => draft[field.id] !== void 0 && draft[field.id] !== format(value[field.id]));
|
|
1339
|
+
const peerTextOf = (field) => {
|
|
1340
|
+
if (field.atLeast === "") return void 0;
|
|
1341
|
+
const related = fields.find((candidate) => candidate.id === field.atLeast);
|
|
1342
|
+
return related === void 0 ? void 0 : textOf(related);
|
|
1343
|
+
};
|
|
1344
|
+
const blocked = fields.some((field) => invalidReason(field, textOf(field), peerTextOf(field)) !== null);
|
|
1161
1345
|
const change = (id, next) => {
|
|
1162
1346
|
setDraft({
|
|
1163
1347
|
...draft,
|
|
@@ -1182,11 +1366,11 @@ window.__ModuleLoader__.load({
|
|
|
1182
1366
|
setPending(null);
|
|
1183
1367
|
setBusy(false);
|
|
1184
1368
|
setClearing(null);
|
|
1185
|
-
if (!
|
|
1186
|
-
setError(t(pending.
|
|
1369
|
+
if (!pending.accepted) {
|
|
1370
|
+
setError(t(pending.resets ? "resetRefused" : "refused"));
|
|
1187
1371
|
return;
|
|
1188
1372
|
}
|
|
1189
|
-
if (pending.
|
|
1373
|
+
if (!pending.resets) setDraft({});
|
|
1190
1374
|
}, [
|
|
1191
1375
|
pending,
|
|
1192
1376
|
snapshot.user,
|
|
@@ -1204,17 +1388,18 @@ window.__ModuleLoader__.load({
|
|
|
1204
1388
|
setClearing(field);
|
|
1205
1389
|
setError("");
|
|
1206
1390
|
(async () => {
|
|
1391
|
+
let accepted;
|
|
1207
1392
|
try {
|
|
1208
|
-
await clear(field);
|
|
1393
|
+
accepted = await clear(field);
|
|
1209
1394
|
} catch (caught) {
|
|
1210
1395
|
setClearing(null);
|
|
1211
1396
|
setError(caught instanceof Error && caught.message !== "" ? caught.message : t("resetRefused"));
|
|
1212
1397
|
return;
|
|
1213
1398
|
}
|
|
1214
|
-
setPending(
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
}
|
|
1399
|
+
setPending({
|
|
1400
|
+
accepted,
|
|
1401
|
+
resets: true
|
|
1402
|
+
});
|
|
1218
1403
|
})();
|
|
1219
1404
|
};
|
|
1220
1405
|
const save = () => {
|
|
@@ -1222,16 +1407,14 @@ window.__ModuleLoader__.load({
|
|
|
1222
1407
|
setError("");
|
|
1223
1408
|
(async () => {
|
|
1224
1409
|
try {
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
want: parseFor(field.control, textOf(field))
|
|
1234
|
-
})));
|
|
1410
|
+
setPending({
|
|
1411
|
+
accepted: await mutateOnce(dirty.map((field) => ({
|
|
1412
|
+
op: "set",
|
|
1413
|
+
path: [field.id],
|
|
1414
|
+
value: parseFor(field.control, textOf(field))
|
|
1415
|
+
}))),
|
|
1416
|
+
resets: false
|
|
1417
|
+
});
|
|
1235
1418
|
} catch (caught) {
|
|
1236
1419
|
setBusy(false);
|
|
1237
1420
|
setError(caught instanceof Error && caught.message !== "" ? caught.message : t("refused"));
|
|
@@ -1245,20 +1428,34 @@ window.__ModuleLoader__.load({
|
|
|
1245
1428
|
onClick: () => {
|
|
1246
1429
|
setOpen(!open);
|
|
1247
1430
|
}
|
|
1248
|
-
}, (0, react.createElement)("span", { className: "evolution-param-card-title" }, title), changed === 0 ? null : (0, react.createElement)("span", { className: "evolution-param-count" }, t("changed"
|
|
1431
|
+
}, (0, react.createElement)("span", { className: "evolution-param-card-title" }, title), changed === 0 ? null : (0, react.createElement)("span", { className: "evolution-param-count" }, t("changed", { n: changed })), (0, react.createElement)("span", { className: "evolution-param-dest" }, snapshot.mode === "memory" ? t("destMemory") : t("destHost")), (0, react.createElement)("span", { className: "evolution-param-chevron" }, open ? "▲" : "▼")), open ? (0, react.createElement)("div", { className: "evolution-param-body" }, disabled ? (0, react.createElement)("p", {
|
|
1432
|
+
className: "evolution-param-note",
|
|
1433
|
+
role: "status"
|
|
1434
|
+
}, t("readonly")) : null, fields.length === 0 ? (0, react.createElement)("p", {
|
|
1435
|
+
className: "evolution-param-note",
|
|
1436
|
+
role: "status"
|
|
1437
|
+
}, t("empty")) : fields.flatMap((field, index) => [index === 0 || fields[index - 1]?.group !== field.group ? (0, react.createElement)("h3", {
|
|
1438
|
+
key: "group-" + field.group,
|
|
1439
|
+
className: "evolution-param-group"
|
|
1440
|
+
}, field.group) : null, (0, react.createElement)(FieldBlock, {
|
|
1249
1441
|
key: field.id,
|
|
1250
1442
|
field,
|
|
1251
1443
|
text: textOf(field),
|
|
1252
1444
|
overridden: Object.hasOwn(user, field.id),
|
|
1253
1445
|
disabled: locked,
|
|
1254
1446
|
clearing: clearing === field.id,
|
|
1447
|
+
resetTo: resetToOf(snapshot.base?.[field.id]),
|
|
1448
|
+
invalid: invalidReason(field, textOf(field), peerTextOf(field)),
|
|
1255
1449
|
t,
|
|
1256
1450
|
onChange: change,
|
|
1257
1451
|
onClear: reset
|
|
1258
|
-
})), error === "" ? null : (0, react.createElement)("p", {
|
|
1452
|
+
})]), error === "" ? null : (0, react.createElement)("p", {
|
|
1453
|
+
className: "evolution-param-error",
|
|
1454
|
+
role: "status"
|
|
1455
|
+
}, error), fields.length === 0 ? null : (0, react.createElement)("div", { className: "evolution-param-footer" }, (0, react.createElement)("button", {
|
|
1259
1456
|
type: "button",
|
|
1260
1457
|
className: "evolution-param-button",
|
|
1261
|
-
disabled: busy || dirty.length === 0,
|
|
1458
|
+
disabled: busy || dirty.length === 0 || blocked,
|
|
1262
1459
|
onClick: () => {
|
|
1263
1460
|
setDraft({});
|
|
1264
1461
|
setError("");
|
|
@@ -1296,6 +1493,8 @@ window.__ModuleLoader__.load({
|
|
|
1296
1493
|
value: void 0,
|
|
1297
1494
|
user: void 0,
|
|
1298
1495
|
writable: false,
|
|
1496
|
+
base: void 0,
|
|
1497
|
+
mode: "host",
|
|
1299
1498
|
reason: "seat-missing"
|
|
1300
1499
|
});
|
|
1301
1500
|
/** What a card shows when the seat served the row but projecting it failed. A frozen constant
|
|
@@ -1306,17 +1505,11 @@ window.__ModuleLoader__.load({
|
|
|
1306
1505
|
value: void 0,
|
|
1307
1506
|
user: void 0,
|
|
1308
1507
|
writable: false,
|
|
1508
|
+
base: void 0,
|
|
1509
|
+
mode: "host",
|
|
1309
1510
|
reason: "projection-failed"
|
|
1310
1511
|
});
|
|
1311
1512
|
/**
|
|
1312
|
-
* Whether a value is a plain section object.
|
|
1313
|
-
* @param value - the value to test.
|
|
1314
|
-
* @returns true for a non-null, non-array object.
|
|
1315
|
-
*/
|
|
1316
|
-
function isSection(value) {
|
|
1317
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1318
|
-
}
|
|
1319
|
-
/**
|
|
1320
1513
|
* Project one platform snapshot into the card's own shape.
|
|
1321
1514
|
* @param snapshot - the seat's snapshot.
|
|
1322
1515
|
* @returns the card's snapshot, with the reason an unavailable one is unavailable.
|
|
@@ -1324,9 +1517,11 @@ window.__ModuleLoader__.load({
|
|
|
1324
1517
|
function sectionSnapshotOf(snapshot) {
|
|
1325
1518
|
return {
|
|
1326
1519
|
status: snapshot.status,
|
|
1327
|
-
value:
|
|
1520
|
+
value: isRecord(snapshot.value) ? snapshot.value : void 0,
|
|
1328
1521
|
user: snapshot.user,
|
|
1329
1522
|
writable: snapshot.writable,
|
|
1523
|
+
base: isRecord(snapshot.base) ? snapshot.base : void 0,
|
|
1524
|
+
mode: snapshot.mode,
|
|
1330
1525
|
...snapshot.status === "unavailable" ? { reason: "not-served" } : {}
|
|
1331
1526
|
};
|
|
1332
1527
|
}
|
|
@@ -1432,10 +1627,16 @@ window.__ModuleLoader__.load({
|
|
|
1432
1627
|
const form = () => probe()?.get(namespace);
|
|
1433
1628
|
return {
|
|
1434
1629
|
mutateOnce: async (ops) => {
|
|
1435
|
-
|
|
1630
|
+
const seat = form();
|
|
1631
|
+
if (seat === void 0) return false;
|
|
1632
|
+
await seat.mutate(ops);
|
|
1633
|
+
return true;
|
|
1436
1634
|
},
|
|
1437
1635
|
clear: async (field) => {
|
|
1438
|
-
|
|
1636
|
+
const seat = form();
|
|
1637
|
+
if (seat === void 0) return false;
|
|
1638
|
+
await seat.unset(field);
|
|
1639
|
+
return true;
|
|
1439
1640
|
}
|
|
1440
1641
|
};
|
|
1441
1642
|
}
|
|
@@ -1485,7 +1686,7 @@ window.__ModuleLoader__.load({
|
|
|
1485
1686
|
* @returns how many of them the user overrode.
|
|
1486
1687
|
*/
|
|
1487
1688
|
function overridden(user, fields) {
|
|
1488
|
-
const layer =
|
|
1689
|
+
const layer = isRecord(user) ? user : {};
|
|
1489
1690
|
return fields.filter((field) => Object.hasOwn(layer, field.id)).length;
|
|
1490
1691
|
}
|
|
1491
1692
|
/**
|
|
@@ -1495,23 +1696,22 @@ window.__ModuleLoader__.load({
|
|
|
1495
1696
|
*/
|
|
1496
1697
|
function RowConfigCard(props) {
|
|
1497
1698
|
const { t, fields, namespace, view, form } = props;
|
|
1498
|
-
if (form === void 0) return view === "summary" ? null : (0, react.createElement)("p", {
|
|
1699
|
+
if (form === void 0) return view === "summary" ? null : (0, react.createElement)("p", {
|
|
1700
|
+
className: "evolution-param-note",
|
|
1701
|
+
role: "status"
|
|
1702
|
+
}, t("seatMissing"));
|
|
1499
1703
|
const changed = overridden(form.state.user, fields);
|
|
1500
|
-
if (view === "summary") return changed === 0 ? null : (0, react.createElement)("span", null, t("changed"
|
|
1704
|
+
if (view === "summary") return changed === 0 ? null : (0, react.createElement)("span", null, t("changed", { n: changed }));
|
|
1501
1705
|
return ParamCardView({
|
|
1502
1706
|
namespace,
|
|
1503
1707
|
fields,
|
|
1504
1708
|
t,
|
|
1505
1709
|
snapshot: sectionSnapshotOf(form.state),
|
|
1506
|
-
mutateOnce: async (ops) =>
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
op: "unset",
|
|
1512
|
-
path: [field]
|
|
1513
|
-
}], form.state.revision);
|
|
1514
|
-
}
|
|
1710
|
+
mutateOnce: async (ops) => form.mutate(ops, form.state.revision),
|
|
1711
|
+
clear: async (field) => form.mutate([{
|
|
1712
|
+
op: "unset",
|
|
1713
|
+
path: [field]
|
|
1714
|
+
}], form.state.revision)
|
|
1515
1715
|
});
|
|
1516
1716
|
}
|
|
1517
1717
|
//#endregion
|
|
@@ -1560,7 +1760,7 @@ window.__ModuleLoader__.load({
|
|
|
1560
1760
|
* @returns the section element.
|
|
1561
1761
|
*/
|
|
1562
1762
|
function SettingsSection(face) {
|
|
1563
|
-
return (0, react.createElement)("div", { className: "evolution-params" }, (0, react.createElement)("h2", { className: "evolution-params-title" }, face.t("title")), (0, react.createElement)("p", { className: "evolution-params-subtitle" }, face.t("subtitle")), (0, react.createElement)("div", {
|
|
1763
|
+
return (0, react.createElement)("div", { className: "evolution-params" }, (0, react.createElement)("h2", { className: "evolution-params-title" }, face.t("title")), (0, react.createElement)("p", { className: "evolution-params-subtitle" }, face.t("subtitle")), (0, react.createElement)("p", { className: "evolution-params-about" }, "0.24.0 · Web settings cards for the evolution family's parameter namespaces"), (0, react.createElement)("div", {
|
|
1564
1764
|
key: PENDING_CARD_KEY,
|
|
1565
1765
|
className: "evolution-params-group"
|
|
1566
1766
|
}, face.renderSlot(CARD_SLOT, {}, { entryKey: PENDING_CARD_KEY })), ...CLIENT_PARAM_SECTIONS.map((section_) => (0, react.createElement)("div", {
|
|
@@ -1608,6 +1808,7 @@ window.__ModuleLoader__.load({
|
|
|
1608
1808
|
".evolution-params{display:flex;flex-direction:column}",
|
|
1609
1809
|
".evolution-params-title{margin:0 0 var(--evo-space-4);color:var(--dsw-alias-label-primary);font-size:var(--evo-type-lg);font-weight:600;line-height:var(--evo-leading-base)}",
|
|
1610
1810
|
".evolution-params-subtitle{margin:0 0 var(--evo-space-16);color:var(--dsw-alias-label-tertiary);font-size:var(--evo-type-xs);line-height:var(--evo-leading-base)}",
|
|
1811
|
+
".evolution-params-about{margin:0 0 var(--evo-space-16);color:var(--dsw-alias-label-tertiary);font-size:var(--evo-type-xs)}",
|
|
1611
1812
|
".evolution-param-card{border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2);border-radius:var(--evo-radius-control);background:var(--dsw-alias-bg-layer-1);margin-bottom:var(--evo-space-12)}",
|
|
1612
1813
|
".evolution-param-head{display:flex;align-items:center;gap:var(--evo-space-8);width:100%;padding:var(--evo-space-12) var(--evo-space-14);background:none;border:0;text-align:left;cursor:pointer;color:inherit;font:inherit}",
|
|
1613
1814
|
".evolution-param-head:hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
@@ -1615,6 +1816,8 @@ window.__ModuleLoader__.load({
|
|
|
1615
1816
|
".evolution-param-count{color:var(--dsw-alias-brand-primary);font-size:var(--evo-type-xs);line-height:var(--evo-leading-base)}",
|
|
1616
1817
|
".evolution-param-chevron{color:var(--dsw-alias-label-tertiary);font-size:var(--evo-type-xs);line-height:var(--evo-leading-base)}",
|
|
1617
1818
|
".evolution-param-body{padding:0 var(--evo-space-14) var(--evo-space-12);border-top:var(--evo-hairline-width) solid var(--dsw-alias-border-l2)}",
|
|
1819
|
+
".evolution-param-dest{color:var(--dsw-alias-label-tertiary);font-size:var(--evo-type-xs)}",
|
|
1820
|
+
".evolution-param-group{margin:var(--evo-space-12) 0 0;font-size:var(--evo-type-sm);font-weight:600;color:var(--dsw-alias-label-secondary);text-transform:none}",
|
|
1618
1821
|
".evolution-param-field{display:flex;flex-direction:column;gap:var(--evo-space-6);padding:var(--evo-space-12) 0}",
|
|
1619
1822
|
".evolution-param-field+.evolution-param-field{border-top:var(--evo-hairline-width) solid var(--dsw-alias-border-l2)}",
|
|
1620
1823
|
".evolution-param-label{display:flex;align-items:center;gap:var(--evo-space-6);color:var(--dsw-alias-label-primary);font-size:var(--evo-type-body);font-weight:500;line-height:var(--evo-leading-base)}",
|
|
@@ -1622,18 +1825,20 @@ window.__ModuleLoader__.load({
|
|
|
1622
1825
|
".evolution-param-hint{margin:0;color:var(--dsw-alias-label-tertiary);font-size:var(--evo-type-sm);line-height:var(--evo-leading-base)}",
|
|
1623
1826
|
".evolution-param-value{color:var(--dsw-alias-label-secondary);font-size:var(--evo-type-xs);line-height:var(--evo-leading-base)}",
|
|
1624
1827
|
".evolution-param-input{width:100%;box-sizing:border-box;padding:var(--evo-space-8) var(--evo-space-10);border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2);border-radius:var(--evo-radius-control);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:var(--evo-type-body);line-height:var(--evo-leading-base)}",
|
|
1625
|
-
".evolution-param-input:focus{outline:var(--evo-focus-ring);outline-offset:var(--evo-focus-offset)}",
|
|
1828
|
+
".evolution-param-input:focus-visible{outline:var(--evo-focus-ring);outline-offset:var(--evo-focus-offset)}",
|
|
1626
1829
|
".evolution-param-input:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}",
|
|
1627
1830
|
".evolution-param-source{display:inline-flex;align-items:center;height:var(--evo-space-20);padding:0 var(--evo-space-6);border-radius:var(--evo-radius-chip);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary);font-size:var(--evo-type-xs);line-height:var(--evo-space-20)}",
|
|
1628
1831
|
".evolution-param-source[data-user=\"true\"]{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground)}",
|
|
1629
1832
|
".evolution-param-actions{display:flex;justify-content:flex-end;gap:var(--evo-space-8);padding-top:var(--evo-space-12)}",
|
|
1630
1833
|
".evolution-param-button{padding:var(--evo-space-6) var(--evo-space-12);border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2);border-radius:var(--evo-radius-control);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:var(--evo-type-sm);line-height:var(--evo-leading-base);cursor:pointer}",
|
|
1631
1834
|
".evolution-param-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}",
|
|
1835
|
+
".evolution-param-button[data-tone=\"outline\"]{border-color:var(--dsw-alias-border-l2)}",
|
|
1836
|
+
".evolution-param-button[data-tone=\"ghost\"]{border-color:transparent;background:transparent}",
|
|
1632
1837
|
".evolution-param-button[data-primary=\"true\"]{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:transparent}",
|
|
1633
1838
|
".evolution-param-button[data-primary=\"true\"]:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}",
|
|
1634
1839
|
".evolution-param-button:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}",
|
|
1635
1840
|
".evolution-param-select{width:100%;box-sizing:border-box;padding:var(--evo-space-8) var(--evo-space-10);border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2);border-radius:var(--evo-radius-control);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:var(--evo-type-sm);line-height:var(--evo-leading-base)}",
|
|
1636
|
-
".evolution-param-select:focus{outline:var(--evo-focus-ring);outline-offset:var(--evo-focus-offset)}",
|
|
1841
|
+
".evolution-param-select:focus-visible{outline:var(--evo-focus-ring);outline-offset:var(--evo-focus-offset)}",
|
|
1637
1842
|
".evolution-param-select:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}",
|
|
1638
1843
|
".evolution-param-check{width:var(--evo-space-16);height:var(--evo-space-16);margin:0;accent-color:var(--dsw-alias-brand-primary);cursor:pointer}",
|
|
1639
1844
|
".evolution-param-check:disabled{cursor:default;opacity:.5}",
|
|
@@ -1696,7 +1901,7 @@ window.__ModuleLoader__.load({
|
|
|
1696
1901
|
}
|
|
1697
1902
|
}, "evolution-settings: dictionaries");
|
|
1698
1903
|
let bound = null;
|
|
1699
|
-
const
|
|
1904
|
+
const translate = (key) => {
|
|
1700
1905
|
if (!registered) return message(key);
|
|
1701
1906
|
if (bound === null) try {
|
|
1702
1907
|
bound = seam.locale.bind(NS);
|
|
@@ -1705,11 +1910,14 @@ window.__ModuleLoader__.load({
|
|
|
1705
1910
|
}
|
|
1706
1911
|
return bound(key);
|
|
1707
1912
|
};
|
|
1913
|
+
const t = (key, values) => values === void 0 ? translate(key) : fill(translate(key), values);
|
|
1708
1914
|
const probe = () => ctx.get("configForms");
|
|
1709
1915
|
const sources = createSourceCache(probe);
|
|
1710
1916
|
ctx.effect(() => () => {
|
|
1711
1917
|
sources.dispose();
|
|
1712
1918
|
}, "evolution-settings: sources");
|
|
1919
|
+
const approvalSource = sources.sourceFor("evolution-approval");
|
|
1920
|
+
const confirmMode = () => confirmModeFrom(approvalSource.getSnapshot().user);
|
|
1713
1921
|
ctx.inject?.(["configForms"], () => {
|
|
1714
1922
|
sources.revive();
|
|
1715
1923
|
});
|
|
@@ -1750,7 +1958,8 @@ window.__ModuleLoader__.load({
|
|
|
1750
1958
|
key: PENDING_CARD_KEY,
|
|
1751
1959
|
inject: () => ({
|
|
1752
1960
|
t,
|
|
1753
|
-
api
|
|
1961
|
+
api,
|
|
1962
|
+
confirmMode
|
|
1754
1963
|
})
|
|
1755
1964
|
}, PendingCard);
|
|
1756
1965
|
});
|