@lmzhen/dsh-evolution-merge-ui 0.32.4 → 0.32.6
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 +4 -8
- package/lib/client.js +402 -136
- package/lib/types/client/MergeStore.d.ts +3 -0
- package/lib/types/client/index.d.ts +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
# @lmzhen/dsh-evolution-merge-ui
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
and never writes skills: row actions are copyable `/evolution merge ...`
|
|
5
|
-
commands.
|
|
3
|
+
Skill-merge view inside the shared evolution workbench. It ships only in the `all` installation form.
|
|
6
4
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
- Four states: loading / ready / empty / failed; view schemaVersion guard.
|
|
11
|
-
- Mounted by the `all` bundle only.
|
|
5
|
+
The view is read-only: action buttons copy the appropriate `/evolution merge` or `/evolution doctor` command; they do not approve, execute, or undo a merge in the browser. Internal run fields (run id, stage, parent, result ref) live under the view's run-details disclosure so the queue and decision facts come first.
|
|
6
|
+
|
|
7
|
+
The host entry intentionally registers nothing. The Loader discovers the `dsh.client` manifest and serves the browser bundle, which registers itself into `evolution.workbench.view` and uses the shared client-kit lifecycle and the four merge read routes.
|
package/lib/client.js
CHANGED
|
@@ -5,28 +5,24 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
-
//#region ../evolution-client-kit/src/
|
|
9
|
-
function interpolate(text, values) {
|
|
10
|
-
if (values === void 0) return text;
|
|
11
|
-
return text.replace(/\{(\w+)\}/g, (_match, key) => String(values[key] ?? ""));
|
|
12
|
-
}
|
|
8
|
+
//#region ../evolution-client-kit/src/workbench-view.ts
|
|
13
9
|
function injectStyles(doc, css, tagId) {
|
|
14
10
|
if (doc === void 0) return () => {};
|
|
15
11
|
doc.querySelector("style[data-plugin-css=\"" + tagId + "\"]")?.remove();
|
|
16
12
|
const tag = doc.createElement("style");
|
|
17
13
|
tag.setAttribute("data-plugin-css", tagId);
|
|
18
14
|
tag.textContent = css;
|
|
19
|
-
doc.head.
|
|
15
|
+
doc.head.appendChild(tag);
|
|
20
16
|
return () => {
|
|
21
17
|
tag.remove();
|
|
22
18
|
};
|
|
23
19
|
}
|
|
24
20
|
/**
|
|
25
|
-
* Register one
|
|
26
|
-
* @param ctx -
|
|
27
|
-
* @param spec -
|
|
21
|
+
* Register one view into `evolution.workbench.view`.
|
|
22
|
+
* @param ctx - client cordis context.
|
|
23
|
+
* @param spec - view identity, copy, styles, component and face factory.
|
|
28
24
|
*/
|
|
29
|
-
function
|
|
25
|
+
function registerWorkbenchView(ctx, spec) {
|
|
30
26
|
const seam = ctx;
|
|
31
27
|
let registered = false;
|
|
32
28
|
ctx.effect(() => {
|
|
@@ -35,12 +31,12 @@ window.__ModuleLoader__.load({
|
|
|
35
31
|
registered = true;
|
|
36
32
|
return dispose;
|
|
37
33
|
} catch (error) {
|
|
38
|
-
ctx.logger.warn(spec.namespace + ":
|
|
34
|
+
ctx.logger.warn(spec.namespace + ": locale refused (" + String(error) + "); the view falls back to the bundle copy");
|
|
39
35
|
return () => {};
|
|
40
36
|
}
|
|
41
37
|
}, spec.namespace + ": locale");
|
|
42
38
|
ctx.effect(() => injectStyles(typeof document === "undefined" ? void 0 : document, spec.styles.css, spec.styles.tagId), spec.namespace + ": styles");
|
|
43
|
-
const fallback = spec.dictionaries
|
|
39
|
+
const fallback = spec.dictionaries.zh;
|
|
44
40
|
const lookup = (key) => {
|
|
45
41
|
const own = fallback[key] ?? key;
|
|
46
42
|
if (!registered) return own;
|
|
@@ -50,47 +46,36 @@ window.__ModuleLoader__.load({
|
|
|
50
46
|
return own;
|
|
51
47
|
}
|
|
52
48
|
};
|
|
53
|
-
const t = (key, values) =>
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
const t = (key, values) => {
|
|
50
|
+
const template = lookup(key);
|
|
51
|
+
if (values === void 0) return template;
|
|
52
|
+
return template.replace(/\{(\w+)\}/g, (match, slot) => values[slot] === void 0 ? match : String(values[slot]));
|
|
53
|
+
};
|
|
54
|
+
seam.slots.inject("evolution.workbench.view", function* () {
|
|
56
55
|
yield seam.slots.register({
|
|
57
|
-
name: "
|
|
56
|
+
name: "evolution.workbench.view",
|
|
58
57
|
id: spec.id,
|
|
59
58
|
order: spec.order,
|
|
60
|
-
label
|
|
61
|
-
|
|
62
|
-
yield seam.slots.register({
|
|
63
|
-
name: "main",
|
|
64
|
-
key: spec.id,
|
|
65
|
-
inject: () => spec.body(t)
|
|
59
|
+
label: () => t("entry.label"),
|
|
60
|
+
inject: () => spec.face(t)
|
|
66
61
|
}, spec.component);
|
|
67
62
|
});
|
|
68
63
|
}
|
|
69
64
|
//#endregion
|
|
70
|
-
//#region ../evolution-client-kit/src/
|
|
65
|
+
//#region ../evolution-client-kit/src/generated/routes.generated.ts
|
|
71
66
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
67
|
+
* Every family host path, generated from evolution-core's HOST_ROUTES (the ONE declaration).
|
|
68
|
+
* A browser half cannot import the host package at runtime (client bundles keep @deepseek-ai/*
|
|
69
|
+
* external), so the table is mirrored here mechanically; a rename in core regenerates all three
|
|
70
|
+
* client copies, and the generator's --check makes a stale copy red.
|
|
75
71
|
*/
|
|
76
|
-
|
|
77
|
-
const get = ctx.get;
|
|
78
|
-
if (typeof get !== "function") return void 0;
|
|
79
|
-
for (const name of ["workspace", "uiWorkspace"]) try {
|
|
80
|
-
const seat = get.call(ctx, name);
|
|
81
|
-
const id = seat?.workspaceId ?? seat?.currentWorkspaceId;
|
|
82
|
-
if (typeof id === "string" && id.trim() !== "") return id;
|
|
83
|
-
} catch {}
|
|
84
|
-
}
|
|
85
|
-
//#endregion
|
|
86
|
-
//#region src/client/api.ts
|
|
87
|
-
/** Read-only merge wire client. Classifies every failure and never writes. */
|
|
88
|
-
const HOST_ROUTES = {
|
|
72
|
+
const ROUTES = {
|
|
89
73
|
approval: {
|
|
90
74
|
pending: "/api/dsh-evolution/approval/pending",
|
|
91
75
|
preview: "/api/dsh-evolution/approval/preview",
|
|
92
76
|
approve: "/api/dsh-evolution/approval/approve",
|
|
93
|
-
reject: "/api/dsh-evolution/approval/reject"
|
|
77
|
+
reject: "/api/dsh-evolution/approval/reject",
|
|
78
|
+
release: "/api/dsh-evolution/approval/release"
|
|
94
79
|
},
|
|
95
80
|
"skill-history": {
|
|
96
81
|
skills: "/api/dsh-evolution/skill-history/skills",
|
|
@@ -109,8 +94,166 @@ window.__ModuleLoader__.load({
|
|
|
109
94
|
body: "/api/dsh-evolution/merge/body",
|
|
110
95
|
history: "/api/dsh-evolution/merge/history"
|
|
111
96
|
},
|
|
112
|
-
diagnostics: { view: "/api/dsh-evolution/diagnostics" }
|
|
113
|
-
|
|
97
|
+
diagnostics: { view: "/api/dsh-evolution/diagnostics" },
|
|
98
|
+
settings: {
|
|
99
|
+
describe: "/api/dsh-evolution/settings/describe",
|
|
100
|
+
mutate: "/api/dsh-evolution/settings/mutate"
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region ../evolution-client-kit/src/settings-seat.ts
|
|
105
|
+
const SETTINGS_DESCRIBE = ROUTES.settings.describe;
|
|
106
|
+
const SETTINGS_MUTATE = ROUTES.settings.mutate;
|
|
107
|
+
const EMPTY = Object.freeze({
|
|
108
|
+
status: "unavailable",
|
|
109
|
+
value: void 0,
|
|
110
|
+
user: void 0,
|
|
111
|
+
writable: false,
|
|
112
|
+
base: void 0,
|
|
113
|
+
revision: void 0,
|
|
114
|
+
reason: "transport"
|
|
115
|
+
});
|
|
116
|
+
function snapshotFrom(value, ns) {
|
|
117
|
+
if (typeof value !== "object" || value === null) return EMPTY;
|
|
118
|
+
const list = value.namespaces;
|
|
119
|
+
if (!Array.isArray(list)) return EMPTY;
|
|
120
|
+
const item = list.find((candidate) => typeof candidate === "object" && candidate !== null && candidate.ns === ns);
|
|
121
|
+
return item === void 0 ? {
|
|
122
|
+
...EMPTY,
|
|
123
|
+
reason: "not-served"
|
|
124
|
+
} : item;
|
|
125
|
+
}
|
|
126
|
+
async function describe(namespace) {
|
|
127
|
+
try {
|
|
128
|
+
const response = await fetch(SETTINGS_DESCRIBE, { headers: { accept: "application/json" } });
|
|
129
|
+
if (!response.ok) return EMPTY;
|
|
130
|
+
const body = await response.json();
|
|
131
|
+
if (body.ok !== true) return EMPTY;
|
|
132
|
+
return snapshotFrom(body.data, namespace);
|
|
133
|
+
} catch {
|
|
134
|
+
return EMPTY;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function write(namespace, ops, expectedRevision) {
|
|
138
|
+
try {
|
|
139
|
+
const response = await fetch(SETTINGS_MUTATE, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: {
|
|
142
|
+
"content-type": "application/json",
|
|
143
|
+
accept: "application/json"
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify({
|
|
146
|
+
ns: namespace,
|
|
147
|
+
ops,
|
|
148
|
+
...expectedRevision === void 0 ? {} : { expectedRevision }
|
|
149
|
+
})
|
|
150
|
+
});
|
|
151
|
+
if (!response.ok) return { ok: false };
|
|
152
|
+
const body = await response.json();
|
|
153
|
+
return {
|
|
154
|
+
ok: body.ok === true,
|
|
155
|
+
snapshot: snapshotFrom(body.data, namespace)
|
|
156
|
+
};
|
|
157
|
+
} catch {
|
|
158
|
+
return { ok: false };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function createForm(namespace, ctx) {
|
|
162
|
+
let snapshot = {
|
|
163
|
+
...EMPTY,
|
|
164
|
+
reason: "seat-missing"
|
|
165
|
+
};
|
|
166
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
167
|
+
let started = false;
|
|
168
|
+
let listening = false;
|
|
169
|
+
const notify = () => {
|
|
170
|
+
for (const listener of listeners) listener();
|
|
171
|
+
};
|
|
172
|
+
const refresh = async () => {
|
|
173
|
+
snapshot = await describe(namespace);
|
|
174
|
+
notify();
|
|
175
|
+
};
|
|
176
|
+
const start = () => {
|
|
177
|
+
if (started) return;
|
|
178
|
+
started = true;
|
|
179
|
+
if (!listening) {
|
|
180
|
+
listening = true;
|
|
181
|
+
(ctx.get?.("remote"))?.$on?.("settings/document-updated", (changed) => {
|
|
182
|
+
if (changed === namespace) refresh();
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
refresh();
|
|
186
|
+
};
|
|
187
|
+
const form = {
|
|
188
|
+
getSnapshot: () => snapshot,
|
|
189
|
+
subscribe: (listener) => {
|
|
190
|
+
listeners.add(listener);
|
|
191
|
+
start();
|
|
192
|
+
return () => {
|
|
193
|
+
listeners.delete(listener);
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
set: async (field, value) => await form.mutate([{
|
|
197
|
+
op: "set",
|
|
198
|
+
path: [field],
|
|
199
|
+
value
|
|
200
|
+
}]),
|
|
201
|
+
unset: async (field) => await form.mutate([{
|
|
202
|
+
op: "unset",
|
|
203
|
+
path: [field]
|
|
204
|
+
}]),
|
|
205
|
+
mutate: async (ops, expectedRevision) => {
|
|
206
|
+
const outcome = await write(namespace, ops, expectedRevision ?? snapshot.revision);
|
|
207
|
+
if (outcome.snapshot !== void 0) {
|
|
208
|
+
snapshot = outcome.snapshot;
|
|
209
|
+
notify();
|
|
210
|
+
} else await refresh();
|
|
211
|
+
return outcome.ok;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
return form;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Build one cached form per family namespace over the family settings routes.
|
|
218
|
+
* @param ctx - the client plugin context (remote subscription is optional).
|
|
219
|
+
* @returns the seat; each namespace is served by /api/dsh-evolution/settings/*.
|
|
220
|
+
*/
|
|
221
|
+
const seats = /* @__PURE__ */ new WeakMap();
|
|
222
|
+
function createSettingsSeat(ctx) {
|
|
223
|
+
const cached = seats.get(ctx);
|
|
224
|
+
if (cached !== void 0) return cached;
|
|
225
|
+
const forms = /* @__PURE__ */ new Map();
|
|
226
|
+
const seat = { get(namespace) {
|
|
227
|
+
let form = forms.get(namespace);
|
|
228
|
+
if (form === void 0) {
|
|
229
|
+
form = createForm(namespace, ctx);
|
|
230
|
+
forms.set(namespace, form);
|
|
231
|
+
}
|
|
232
|
+
return form;
|
|
233
|
+
} };
|
|
234
|
+
seats.set(ctx, seat);
|
|
235
|
+
return seat;
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region ../evolution-client-kit/src/workspace.ts
|
|
239
|
+
/**
|
|
240
|
+
* Best-effort workspace id; a seat that is absent or refuses leaves the panel in local scope.
|
|
241
|
+
* @param ctx - the client context.
|
|
242
|
+
* @returns the current workspace id, or undefined.
|
|
243
|
+
*/
|
|
244
|
+
function panelWorkspaceId(ctx) {
|
|
245
|
+
const get = ctx.get;
|
|
246
|
+
if (typeof get !== "function") return void 0;
|
|
247
|
+
for (const name of ["workspace", "uiWorkspace"]) try {
|
|
248
|
+
const seat = get.call(ctx, name);
|
|
249
|
+
const id = seat?.workspaceId ?? seat?.currentWorkspaceId;
|
|
250
|
+
if (typeof id === "string" && id.trim() !== "") return id;
|
|
251
|
+
} catch {}
|
|
252
|
+
}
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/client/api.ts
|
|
255
|
+
/** Read-only merge wire client. Classifies every failure and never writes. */
|
|
256
|
+
const HOST_ROUTES = ROUTES.merge;
|
|
114
257
|
const isBlocked = (failure) => failure.kind === "blocked";
|
|
115
258
|
const asReadiness = (value) => {
|
|
116
259
|
const raw = typeof value === "object" && value !== null ? value : {};
|
|
@@ -348,7 +491,7 @@ window.__ModuleLoader__.load({
|
|
|
348
491
|
startCommands: facts.startCommands,
|
|
349
492
|
notes: [...facts.notes],
|
|
350
493
|
degraded: facts.degraded,
|
|
351
|
-
...facts.
|
|
494
|
+
...facts.active === null && facts.last === null ? {} : { latestRun: toRun(facts.active ?? facts.last) },
|
|
352
495
|
approval: {
|
|
353
496
|
mergeApproval: facts.approval.mergeApproval,
|
|
354
497
|
...platformWrite === void 0 ? {} : { platformWrite }
|
|
@@ -426,6 +569,7 @@ window.__ModuleLoader__.load({
|
|
|
426
569
|
"start.pair": "复制配对命令模板",
|
|
427
570
|
"degraded": "读模型降级:",
|
|
428
571
|
"copied": "已复制:",
|
|
572
|
+
"copyFailed": "复制失败:浏览器没有接受剪贴板写入。",
|
|
429
573
|
"row.noSummary": "无摘要",
|
|
430
574
|
"overlay.body": "正文",
|
|
431
575
|
"hint": "手动触发;后台逐对判定。这里只读,不写技能。",
|
|
@@ -441,6 +585,7 @@ window.__ModuleLoader__.load({
|
|
|
441
585
|
"empty.fuse": "没有待合并的对。",
|
|
442
586
|
"empty.skipped": "没有标记为无需合并的对。",
|
|
443
587
|
"loading": "正在读取…",
|
|
588
|
+
"refreshing": "刷新中,下面仍是上次结果…",
|
|
444
589
|
"refresh": "刷新",
|
|
445
590
|
"loadMore": "加载更多",
|
|
446
591
|
"approval.on": "审批开:合并前需人工批准。",
|
|
@@ -489,13 +634,13 @@ window.__ModuleLoader__.load({
|
|
|
489
634
|
"skipKind.forced": "强制",
|
|
490
635
|
"action.approve": "复制批准",
|
|
491
636
|
"action.reject": "复制拒绝",
|
|
492
|
-
"action.retry-candidates": "
|
|
637
|
+
"action.retry-candidates": "复制重试候选",
|
|
493
638
|
"action.retry-resume": "重试续跑",
|
|
494
639
|
"action.discard": "复制丢弃",
|
|
495
|
-
"action.restore": "
|
|
640
|
+
"action.restore": "复制恢复命令",
|
|
496
641
|
"action.pair": "复制配对",
|
|
497
|
-
"action.status": "
|
|
498
|
-
"action.report": "
|
|
642
|
+
"action.status": "复制状态命令",
|
|
643
|
+
"action.report": "复制报告命令",
|
|
499
644
|
"action.cancel": "取消",
|
|
500
645
|
"action.confirm": "确认复制",
|
|
501
646
|
"disabled.expired": "已过期,不可用",
|
|
@@ -505,6 +650,7 @@ window.__ModuleLoader__.load({
|
|
|
505
650
|
"disabled.owned": "已有运行",
|
|
506
651
|
"disabled.unavailable": "暂不可用",
|
|
507
652
|
"history.empty": "没有历史。",
|
|
653
|
+
"history.archivedAt": "归档于 {date}",
|
|
508
654
|
"failureServer": "读取失败",
|
|
509
655
|
"failureUnauthorized": "未登录",
|
|
510
656
|
"failureForbidden": "无权访问",
|
|
@@ -592,6 +738,7 @@ window.__ModuleLoader__.load({
|
|
|
592
738
|
"run.currentPair": "当前对",
|
|
593
739
|
"run.parent": "父运行",
|
|
594
740
|
"run.report": "报告",
|
|
741
|
+
"run.details": "运行详情",
|
|
595
742
|
"run.noReport": "暂无报告",
|
|
596
743
|
"run.resultRef": "报告位置",
|
|
597
744
|
"run.actions": "运行操作",
|
|
@@ -609,7 +756,7 @@ window.__ModuleLoader__.load({
|
|
|
609
756
|
"error.title": "读取失败",
|
|
610
757
|
"error.retry": "重试",
|
|
611
758
|
"error.raw": "原始信息",
|
|
612
|
-
"doctor.open": "
|
|
759
|
+
"doctor.open": "复制诊断命令",
|
|
613
760
|
"sort.updatedAt": "按更新时间",
|
|
614
761
|
"sort.score": "按分数",
|
|
615
762
|
"pin": "置顶",
|
|
@@ -622,6 +769,7 @@ window.__ModuleLoader__.load({
|
|
|
622
769
|
"start.pair": "Copy pair command template",
|
|
623
770
|
"degraded": "Degraded read model:",
|
|
624
771
|
"copied": "Copied:",
|
|
772
|
+
"copyFailed": "Copy failed: the browser did not accept the clipboard write.",
|
|
625
773
|
"row.noSummary": "No summary",
|
|
626
774
|
"overlay.body": "Body",
|
|
627
775
|
"hint": "Manual only; pairs are judged in the background. Read-only here.",
|
|
@@ -637,6 +785,7 @@ window.__ModuleLoader__.load({
|
|
|
637
785
|
"empty.fuse": "No pairs ready to merge.",
|
|
638
786
|
"empty.skipped": "No pairs marked as not worth merging.",
|
|
639
787
|
"loading": "Loading…",
|
|
788
|
+
"refreshing": "Refreshing; the rows below are the previous result…",
|
|
640
789
|
"refresh": "Refresh",
|
|
641
790
|
"loadMore": "Load more",
|
|
642
791
|
"approval.on": "Approval on: merges wait for a human.",
|
|
@@ -685,13 +834,13 @@ window.__ModuleLoader__.load({
|
|
|
685
834
|
"skipKind.forced": "forced",
|
|
686
835
|
"action.approve": "Copy approve",
|
|
687
836
|
"action.reject": "Copy reject",
|
|
688
|
-
"action.retry-candidates": "
|
|
837
|
+
"action.retry-candidates": "Copy retry candidates",
|
|
689
838
|
"action.retry-resume": "Retry resume",
|
|
690
839
|
"action.discard": "Copy discard",
|
|
691
|
-
"action.restore": "
|
|
840
|
+
"action.restore": "Copy restore command",
|
|
692
841
|
"action.pair": "Copy pair",
|
|
693
|
-
"action.status": "
|
|
694
|
-
"action.report": "
|
|
842
|
+
"action.status": "Copy status command",
|
|
843
|
+
"action.report": "Copy report command",
|
|
695
844
|
"action.cancel": "Cancel",
|
|
696
845
|
"action.confirm": "Copy confirmation",
|
|
697
846
|
"disabled.expired": "expired",
|
|
@@ -701,6 +850,7 @@ window.__ModuleLoader__.load({
|
|
|
701
850
|
"disabled.owned": "already running",
|
|
702
851
|
"disabled.unavailable": "unavailable",
|
|
703
852
|
"history.empty": "No history.",
|
|
853
|
+
"history.archivedAt": "Archived {date}",
|
|
704
854
|
"failureServer": "Read failed",
|
|
705
855
|
"failureUnauthorized": "Not signed in",
|
|
706
856
|
"failureForbidden": "Forbidden",
|
|
@@ -788,6 +938,7 @@ window.__ModuleLoader__.load({
|
|
|
788
938
|
"run.currentPair": "Current pair",
|
|
789
939
|
"run.parent": "Parent run",
|
|
790
940
|
"run.report": "Report",
|
|
941
|
+
"run.details": "Run details",
|
|
791
942
|
"run.noReport": "No report yet",
|
|
792
943
|
"run.resultRef": "Report location",
|
|
793
944
|
"run.actions": "Run actions",
|
|
@@ -805,7 +956,7 @@ window.__ModuleLoader__.load({
|
|
|
805
956
|
"error.title": "Read failed",
|
|
806
957
|
"error.retry": "Retry",
|
|
807
958
|
"error.raw": "Raw message",
|
|
808
|
-
"doctor.open": "
|
|
959
|
+
"doctor.open": "Copy diagnostics command",
|
|
809
960
|
"sort.updatedAt": "Last updated",
|
|
810
961
|
"sort.score": "Score",
|
|
811
962
|
"pin": "Pin",
|
|
@@ -815,12 +966,14 @@ window.__ModuleLoader__.load({
|
|
|
815
966
|
"settings.saved": "已保存",
|
|
816
967
|
"settings.saveFailed": "保存失败",
|
|
817
968
|
"settings.openPlatform": "打开平台设置",
|
|
969
|
+
"settings.openPlatformPath": "设置 → 内置插件 → 插件配置 → 技能自动合并",
|
|
818
970
|
"settings.live": "可直接在此保存;platformWrite 能力来自宿主。"
|
|
819
971
|
});
|
|
820
972
|
Object.assign(en, {
|
|
821
973
|
"settings.saved": "Saved",
|
|
822
974
|
"settings.saveFailed": "Save failed",
|
|
823
975
|
"settings.openPlatform": "Open platform settings",
|
|
976
|
+
"settings.openPlatformPath": "Settings → Built-in plugins → Plugin configuration → Skill auto-merge",
|
|
824
977
|
"settings.live": "Save directly here; platformWrite capability comes from the host."
|
|
825
978
|
});
|
|
826
979
|
Object.assign(zh, { "settings.platformWriteLinkHint": "此开关属于平台设置,这里只读;请到平台设置修改。" });
|
|
@@ -850,7 +1003,7 @@ window.__ModuleLoader__.load({
|
|
|
850
1003
|
".evolution-merge-panel [data-role=\"stat\"] { border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); padding:var(--evo-space-6) var(--evo-space-10); min-width:calc(var(--evo-space-16) * 4); }",
|
|
851
1004
|
".evolution-merge-panel [data-role=\"stat-value\"] { font-size:var(--evo-type-lg); font-weight:600; }",
|
|
852
1005
|
".evolution-merge-panel [data-role=\"stat-label\"] { font-size:var(--evo-type-xs); color:var(--dsw-alias-label-tertiary); }",
|
|
853
|
-
".evolution-merge-panel [data-role=\"tabs\"] { display:flex; gap:var(--evo-space-6); border-bottom:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); }",
|
|
1006
|
+
".evolution-merge-panel [data-role=\"tabs\"] { display:flex; flex-wrap:wrap; gap:var(--evo-space-6); border-bottom:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); }",
|
|
854
1007
|
".evolution-merge-panel [data-role=\"tab\"] { background:none; border:0; border-bottom:var(--evo-hairline-width) solid transparent; padding:var(--evo-space-6) var(--evo-space-8); cursor:pointer; color:inherit; }",
|
|
855
1008
|
".evolution-merge-panel [data-role=\"tab\"][data-active=\"true\"] { border-bottom-color:var(--dsw-alias-brand-primary); }",
|
|
856
1009
|
".evolution-merge-panel button:focus-visible { outline:2px solid currentColor !important; outline-offset:2px; box-shadow:0 0 0 2px currentColor !important; }",
|
|
@@ -1171,19 +1324,43 @@ window.__ModuleLoader__.load({
|
|
|
1171
1324
|
if (run === void 0) return null;
|
|
1172
1325
|
const report = run.actions.find((action) => action.id === "report");
|
|
1173
1326
|
const reportEnabled = report?.enabled === true;
|
|
1327
|
+
const internals = [
|
|
1328
|
+
(0, react.createElement)("span", {
|
|
1329
|
+
key: "id",
|
|
1330
|
+
"data-role": "run-id",
|
|
1331
|
+
title: run.id
|
|
1332
|
+
}, t("run.id") + " " + run.id),
|
|
1333
|
+
run.stage === void 0 ? null : (0, react.createElement)("span", {
|
|
1334
|
+
key: "stage",
|
|
1335
|
+
"data-role": "run-stage"
|
|
1336
|
+
}, t("stage." + run.stage)),
|
|
1337
|
+
run.endedAt === void 0 ? null : (0, react.createElement)("span", {
|
|
1338
|
+
key: "ended",
|
|
1339
|
+
"data-role": "run-ended"
|
|
1340
|
+
}, t("run.endedAt") + " " + new Date(run.endedAt).toLocaleString()),
|
|
1341
|
+
run.failure === void 0 ? null : (0, react.createElement)("span", {
|
|
1342
|
+
key: "failure",
|
|
1343
|
+
"data-role": "run-failure",
|
|
1344
|
+
title: run.failure.detail
|
|
1345
|
+
}, t("run.failure") + " " + run.failure.code),
|
|
1346
|
+
run.currentPairKey === void 0 ? null : (0, react.createElement)("span", {
|
|
1347
|
+
key: "pair",
|
|
1348
|
+
"data-role": "run-current-pair"
|
|
1349
|
+
}, t("run.currentPair") + " " + run.currentPairKey),
|
|
1350
|
+
run.parentRunId === void 0 ? null : (0, react.createElement)("span", {
|
|
1351
|
+
key: "parent",
|
|
1352
|
+
"data-role": "run-parent"
|
|
1353
|
+
}, t("run.parent") + " " + run.parentRunId),
|
|
1354
|
+
run.resultRef === void 0 ? null : (0, react.createElement)("span", {
|
|
1355
|
+
key: "ref",
|
|
1356
|
+
"data-role": "run-result-ref",
|
|
1357
|
+
title: run.resultRef
|
|
1358
|
+
}, t("run.resultRef"))
|
|
1359
|
+
];
|
|
1174
1360
|
return (0, react.createElement)("div", {
|
|
1175
1361
|
"data-role": "run-strip",
|
|
1176
1362
|
"data-run-state": run.state
|
|
1177
|
-
}, (0, react.createElement)("span", {
|
|
1178
|
-
"data-role": "run-id",
|
|
1179
|
-
title: run.id
|
|
1180
|
-
}, t("run.id") + " " + run.id), (0, react.createElement)("span", { "data-role": "run-state" }, t("run.state") + " " + t("run." + run.state)), run.stage === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-stage" }, t("stage." + run.stage)), run.progress === null || run.progress === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-progress" }, t("run.progress") + " " + String(run.progress.done) + "/" + String(run.progress.total)), run.endedAt === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-ended" }, t("run.endedAt") + " " + new Date(run.endedAt).toLocaleString()), run.failure === void 0 ? null : (0, react.createElement)("span", {
|
|
1181
|
-
"data-role": "run-failure",
|
|
1182
|
-
title: run.failure.detail
|
|
1183
|
-
}, t("run.failure") + " " + run.failure.code), run.currentPairKey === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-current-pair" }, t("run.currentPair") + " " + run.currentPairKey), run.parentRunId === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-parent" }, t("run.parent") + " " + run.parentRunId), run.resultRef === void 0 ? null : (0, react.createElement)("span", {
|
|
1184
|
-
"data-role": "run-result-ref",
|
|
1185
|
-
title: run.resultRef
|
|
1186
|
-
}, t("run.resultRef")), (0, react.createElement)("button", {
|
|
1363
|
+
}, (0, react.createElement)("span", { "data-role": "run-state" }, t("run.state") + " " + t("run." + run.state)), run.progress === null || run.progress === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-progress" }, t("run.progress") + " " + String(run.progress.done) + "/" + String(run.progress.total)), (0, react.createElement)("button", {
|
|
1187
1364
|
type: "button",
|
|
1188
1365
|
"data-role": "run-report",
|
|
1189
1366
|
"data-action": "report",
|
|
@@ -1202,7 +1379,7 @@ window.__ModuleLoader__.load({
|
|
|
1202
1379
|
onClick: () => {
|
|
1203
1380
|
if (action.enabled) copy(action.command);
|
|
1204
1381
|
}
|
|
1205
|
-
}, t("action." + action.id))));
|
|
1382
|
+
}, t("action." + action.id))), (0, react.createElement)("details", { "data-role": "run-details" }, (0, react.createElement)("summary", null, t("run.details")), ...internals));
|
|
1206
1383
|
}
|
|
1207
1384
|
function ReadOnlySetting({ section, label, value, disabled, missing, note, link, t }) {
|
|
1208
1385
|
const text = missing ? t("settings.capabilityMissing") : disabled ? t("settings.capabilityDisabled") : value === true ? t("settings.on") : t("settings.off");
|
|
@@ -1213,19 +1390,7 @@ window.__ModuleLoader__.load({
|
|
|
1213
1390
|
}, (0, react.createElement)("span", { "data-role": "settings-label" }, label), (0, react.createElement)("span", {
|
|
1214
1391
|
"data-role": "settings-value",
|
|
1215
1392
|
"data-value": missing ? "missing" : disabled ? "unavailable" : value === true ? "on" : "off"
|
|
1216
|
-
}, text), note === void 0 ? null : (0, react.createElement)("span", { "data-role": "settings-note" }, note), link === true ? (0, react.createElement)("
|
|
1217
|
-
"data-role": "settings-link",
|
|
1218
|
-
href: "#/settings",
|
|
1219
|
-
onClick: () => {
|
|
1220
|
-
window.dispatchEvent(new KeyboardEvent("keydown", {
|
|
1221
|
-
key: ",",
|
|
1222
|
-
code: "Comma",
|
|
1223
|
-
ctrlKey: true,
|
|
1224
|
-
altKey: true,
|
|
1225
|
-
bubbles: true
|
|
1226
|
-
}));
|
|
1227
|
-
}
|
|
1228
|
-
}, t("settings.openPlatform")) : null);
|
|
1393
|
+
}, text), note === void 0 ? null : (0, react.createElement)("span", { "data-role": "settings-note" }, note), link === true ? (0, react.createElement)("span", { "data-role": "settings-link" }, t("settings.openPlatformPath")) : null);
|
|
1229
1394
|
}
|
|
1230
1395
|
function EditableSetting({ form, field, label, fallback, capability, t }) {
|
|
1231
1396
|
const subscribe = (0, react.useCallback)((listener) => form.subscribe(listener), [form]);
|
|
@@ -1258,7 +1423,12 @@ window.__ModuleLoader__.load({
|
|
|
1258
1423
|
"data-role": "settings-section",
|
|
1259
1424
|
"data-section": field === "mergeApproval" ? "merge-approval" : "platform-write",
|
|
1260
1425
|
...disabled ? { "data-disabled": "true" } : {}
|
|
1261
|
-
}, (0, react.createElement)("label", {
|
|
1426
|
+
}, (0, react.createElement)("label", {
|
|
1427
|
+
"data-role": "settings-label",
|
|
1428
|
+
htmlFor: "merge-setting-" + field
|
|
1429
|
+
}, label), (0, react.createElement)("input", {
|
|
1430
|
+
id: "merge-setting-" + field,
|
|
1431
|
+
"aria-label": label,
|
|
1262
1432
|
type: "checkbox",
|
|
1263
1433
|
role: "switch",
|
|
1264
1434
|
"data-role": "settings-toggle",
|
|
@@ -1303,12 +1473,9 @@ window.__ModuleLoader__.load({
|
|
|
1303
1473
|
note: t("settings.platformWriteLinkHint"),
|
|
1304
1474
|
link: true,
|
|
1305
1475
|
t
|
|
1306
|
-
}), settings?.merge === void 0 ? (
|
|
1307
|
-
"data-role": "settings-link",
|
|
1308
|
-
href: "#/settings"
|
|
1309
|
-
}, t("settings.openPlatform")) : null, (0, react.createElement)("p", { "data-role": "settings-readonly" }, settings?.merge === void 0 ? t("settings.readonly") : t("settings.live")));
|
|
1476
|
+
}), (0, react.createElement)("p", { "data-role": "settings-readonly" }, settings?.merge === void 0 ? t("settings.readonly") : t("settings.live")));
|
|
1310
1477
|
}
|
|
1311
|
-
function rowNode(row,
|
|
1478
|
+
function rowNode(row, t, copy, sort, openBody) {
|
|
1312
1479
|
const facts = [
|
|
1313
1480
|
row.target === void 0 ? void 0 : t("row.target") + " " + row.target,
|
|
1314
1481
|
row.targetActual === void 0 ? void 0 : t("row.actualTarget") + " " + row.targetActual,
|
|
@@ -1330,7 +1497,6 @@ window.__ModuleLoader__.load({
|
|
|
1330
1497
|
disabled: !action.enabled,
|
|
1331
1498
|
onClick: () => {
|
|
1332
1499
|
if (!action.enabled) return;
|
|
1333
|
-
if (action.confirm && globalThis.confirm !== void 0 && !globalThis.confirm(t("action.confirm") + " " + (t("action." + action.id) || action.id))) return;
|
|
1334
1500
|
copy(action.command);
|
|
1335
1501
|
}
|
|
1336
1502
|
}, t("action." + action.id)));
|
|
@@ -1341,7 +1507,15 @@ window.__ModuleLoader__.load({
|
|
|
1341
1507
|
"data-row-state": row.state,
|
|
1342
1508
|
"data-row-queue": row.queue,
|
|
1343
1509
|
draggable: true,
|
|
1510
|
+
tabIndex: 0,
|
|
1344
1511
|
title: t("sort.drag"),
|
|
1512
|
+
"aria-haspopup": "menu",
|
|
1513
|
+
onKeyDown: (event) => {
|
|
1514
|
+
if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
|
|
1515
|
+
event.preventDefault();
|
|
1516
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
1517
|
+
sort.menu(row.id, box.left + 12, box.top + 12);
|
|
1518
|
+
},
|
|
1345
1519
|
onDragStart: (event) => {
|
|
1346
1520
|
if (event.dataTransfer != null) {
|
|
1347
1521
|
event.dataTransfer.setData("text/plain", row.id);
|
|
@@ -1375,29 +1549,56 @@ window.__ModuleLoader__.load({
|
|
|
1375
1549
|
key: "a",
|
|
1376
1550
|
type: "button",
|
|
1377
1551
|
"data-role": "body-a",
|
|
1552
|
+
"aria-label": t("body." + bodyA.side) + " " + bodyA.name,
|
|
1553
|
+
title: t("body." + bodyA.side) + " " + bodyA.name,
|
|
1378
1554
|
onClick: () => {
|
|
1379
|
-
|
|
1555
|
+
openBody(bodyA.name, bodyA.side, bodyA.rowId);
|
|
1380
1556
|
}
|
|
1381
1557
|
}, "A"), bodyB === void 0 ? null : (0, react.createElement)("button", {
|
|
1382
1558
|
key: "b",
|
|
1383
1559
|
type: "button",
|
|
1384
1560
|
"data-role": "body-b",
|
|
1561
|
+
"aria-label": t("body." + bodyB.side) + " " + bodyB.name,
|
|
1562
|
+
title: t("body." + bodyB.side) + " " + bodyB.name,
|
|
1385
1563
|
onClick: () => {
|
|
1386
|
-
|
|
1564
|
+
openBody(bodyB.name, bodyB.side, bodyB.rowId);
|
|
1387
1565
|
}
|
|
1388
1566
|
}, "B")];
|
|
1389
1567
|
})(), actions)));
|
|
1390
1568
|
}
|
|
1569
|
+
const overlayKey = (event, onClose) => {
|
|
1570
|
+
if (event.key === "Escape") {
|
|
1571
|
+
event.preventDefault();
|
|
1572
|
+
onClose();
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
if (event.key !== "Tab") return;
|
|
1576
|
+
const nodes = [...event.currentTarget.querySelectorAll("button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])")].filter((node) => !node.hasAttribute("disabled"));
|
|
1577
|
+
if (nodes.length === 0) return;
|
|
1578
|
+
const first = nodes[0];
|
|
1579
|
+
const last = nodes[nodes.length - 1];
|
|
1580
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
1581
|
+
event.preventDefault();
|
|
1582
|
+
last.focus();
|
|
1583
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
1584
|
+
event.preventDefault();
|
|
1585
|
+
first.focus();
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1391
1588
|
function bodyNode(overlay, t, onClose) {
|
|
1392
1589
|
return (0, react.createElement)("section", {
|
|
1393
1590
|
"data-role": "overlay",
|
|
1394
1591
|
"data-overlay": "body",
|
|
1395
1592
|
role: "dialog",
|
|
1396
1593
|
"aria-modal": "true",
|
|
1397
|
-
"aria-label": t("overlay.body")
|
|
1594
|
+
"aria-label": t("overlay.body"),
|
|
1595
|
+
onKeyDown: (event) => {
|
|
1596
|
+
overlayKey(event, onClose);
|
|
1597
|
+
}
|
|
1398
1598
|
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, t("overlay.body") + " · " + overlay.name), (0, react.createElement)("button", {
|
|
1399
1599
|
type: "button",
|
|
1400
1600
|
"data-role": "overlay-close",
|
|
1601
|
+
autoFocus: true,
|
|
1401
1602
|
onClick: onClose
|
|
1402
1603
|
}, t("close"))), (0, react.createElement)("p", { "data-role": "overlay-meta" }, t("body." + overlay.side) + " · " + (overlay.status === "ready" ? t("body.totalBytes") + " " + String(overlay.body?.totalBytes ?? 0) : "")), overlay.status === "loading" ? (0, react.createElement)("p", { "data-role": "overlay-loading" }, t("loading")) : null, overlay.status === "error" && overlay.failure !== void 0 ? failureNode(t, overlay.failure, [], () => {}) : null, overlay.status === "ready" && overlay.body !== void 0 ? (0, react.createElement)("div", null, overlay.body.truncated ? (0, react.createElement)("p", { "data-role": "body-truncated" }, t("body.truncated")) : null, overlay.body.text === "" ? (0, react.createElement)("p", { "data-role": "body-empty" }, t("body.empty")) : (0, react.createElement)("pre", { "data-role": "body-text" }, overlay.body.text)) : null);
|
|
1403
1604
|
}
|
|
@@ -1407,10 +1608,17 @@ window.__ModuleLoader__.load({
|
|
|
1407
1608
|
"data-overlay": "history",
|
|
1408
1609
|
role: "dialog",
|
|
1409
1610
|
"aria-modal": "true",
|
|
1410
|
-
"aria-label": t("history")
|
|
1611
|
+
"aria-label": t("history"),
|
|
1612
|
+
onKeyDown: (event) => {
|
|
1613
|
+
if (event.key === "Escape") {
|
|
1614
|
+
event.preventDefault();
|
|
1615
|
+
onClose();
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1411
1618
|
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, t("history")), (0, react.createElement)("button", {
|
|
1412
1619
|
type: "button",
|
|
1413
1620
|
"data-role": "overlay-close",
|
|
1621
|
+
autoFocus: true,
|
|
1414
1622
|
onClick: onClose
|
|
1415
1623
|
}, t("close"))), overlay.status === "loading" ? (0, react.createElement)("p", { "data-role": "overlay-loading" }, t("loading")) : null, overlay.status === "error" && overlay.failure !== void 0 ? failureNode(t, overlay.failure, [], () => {}) : null, overlay.status === "ready" ? overlay.items === void 0 || overlay.items.length === 0 ? (0, react.createElement)("p", { "data-role": "history-empty" }, t("history.empty")) : (0, react.createElement)("ul", { "data-role": "history-list" }, overlay.items.map((item) => (0, react.createElement)("li", {
|
|
1416
1624
|
key: item.name + ":" + item.archivedAt,
|
|
@@ -1419,20 +1627,51 @@ window.__ModuleLoader__.load({
|
|
|
1419
1627
|
const kind = t("history.kind." + item.kind);
|
|
1420
1628
|
const reason = reasonText(t, item.reasonCode, item.reason);
|
|
1421
1629
|
return kind === reason ? kind : kind + " · " + reason;
|
|
1422
|
-
})() + " · v" + String(item.lastVersion)))) : null);
|
|
1630
|
+
})() + " · v" + String(item.lastVersion) + " · " + t("history.archivedAt", { date: new Date(item.archivedAt).toLocaleString() })))) : null);
|
|
1423
1631
|
}
|
|
1424
1632
|
function MergePanel(face) {
|
|
1425
1633
|
const { store, t } = face;
|
|
1426
1634
|
const snapshot = (0, react.useSyncExternalStore)(store.subscribe, store.read, store.read);
|
|
1427
|
-
const [
|
|
1635
|
+
const [copyState, setCopyState] = (0, react.useState)({ kind: "idle" });
|
|
1428
1636
|
const [orders, setOrders] = (0, react.useState)({});
|
|
1429
1637
|
const [dragId, setDragId] = (0, react.useState)(void 0);
|
|
1430
1638
|
const [menu, setMenu] = (0, react.useState)(void 0);
|
|
1639
|
+
const returnFocus = (0, react.useRef)(null);
|
|
1640
|
+
const captureFocus = () => {
|
|
1641
|
+
returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1642
|
+
};
|
|
1643
|
+
const openBody = (name, side, rowId) => {
|
|
1644
|
+
captureFocus();
|
|
1645
|
+
store.openBody(name, side, rowId);
|
|
1646
|
+
};
|
|
1647
|
+
const openHistory = () => {
|
|
1648
|
+
captureFocus();
|
|
1649
|
+
store.openHistory();
|
|
1650
|
+
};
|
|
1651
|
+
const closeOverlay = () => {
|
|
1652
|
+
store.closeOverlay();
|
|
1653
|
+
requestAnimationFrame(() => {
|
|
1654
|
+
returnFocus.current?.focus();
|
|
1655
|
+
});
|
|
1656
|
+
};
|
|
1431
1657
|
const workspaceId = resolveWorkspaceId(face.workspaceId);
|
|
1432
1658
|
const orderStore = (0, react.useMemo)(() => createRowOrderStore(), []);
|
|
1433
1659
|
const copy = (command) => {
|
|
1434
|
-
|
|
1435
|
-
|
|
1660
|
+
(async () => {
|
|
1661
|
+
try {
|
|
1662
|
+
if (navigator.clipboard?.writeText === void 0) throw new Error("clipboard unavailable");
|
|
1663
|
+
await navigator.clipboard.writeText(command);
|
|
1664
|
+
setCopyState({
|
|
1665
|
+
kind: "copied",
|
|
1666
|
+
text: command
|
|
1667
|
+
});
|
|
1668
|
+
} catch {
|
|
1669
|
+
setCopyState({
|
|
1670
|
+
kind: "failed",
|
|
1671
|
+
text: command
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
})();
|
|
1436
1675
|
};
|
|
1437
1676
|
const doctorCommand = face.doctorCommand ?? DOCTOR_COMMAND;
|
|
1438
1677
|
(0, react.useEffect)(() => {
|
|
@@ -1503,19 +1742,37 @@ window.__ModuleLoader__.load({
|
|
|
1503
1742
|
saveOrder(pinRow(visibleRows.map((row) => row.id), menu.id, edge));
|
|
1504
1743
|
setMenu(void 0);
|
|
1505
1744
|
};
|
|
1745
|
+
const onTabKey = (event, current) => {
|
|
1746
|
+
const delta = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
|
|
1747
|
+
const isEdge = event.key === "Home" || event.key === "End";
|
|
1748
|
+
if (delta === 0 && !isEdge) return;
|
|
1749
|
+
event.preventDefault();
|
|
1750
|
+
const index = QUEUES.indexOf(current);
|
|
1751
|
+
const next = event.key === "Home" ? QUEUES[0] : event.key === "End" ? QUEUES[QUEUES.length - 1] : QUEUES[(index + delta + QUEUES.length) % QUEUES.length];
|
|
1752
|
+
store.select(next);
|
|
1753
|
+
requestAnimationFrame(() => {
|
|
1754
|
+
document.getElementById("merge-tab-" + next)?.focus();
|
|
1755
|
+
});
|
|
1756
|
+
};
|
|
1506
1757
|
const tabs = (0, react.createElement)("div", {
|
|
1507
1758
|
"data-role": "tabs",
|
|
1508
1759
|
role: "tablist"
|
|
1509
1760
|
}, QUEUES.map((item) => (0, react.createElement)("button", {
|
|
1510
1761
|
key: item,
|
|
1762
|
+
id: "merge-tab-" + item,
|
|
1511
1763
|
type: "button",
|
|
1512
1764
|
role: "tab",
|
|
1513
1765
|
"aria-selected": snapshot.queue === item ? "true" : "false",
|
|
1766
|
+
"aria-controls": "merge-rows",
|
|
1767
|
+
tabIndex: snapshot.queue === item ? 0 : -1,
|
|
1514
1768
|
"data-role": "tab",
|
|
1515
1769
|
"data-active": snapshot.queue === item ? "true" : "false",
|
|
1516
1770
|
onClick: () => {
|
|
1517
1771
|
setMenu(void 0);
|
|
1518
1772
|
store.select(item);
|
|
1773
|
+
},
|
|
1774
|
+
onKeyDown: (event) => {
|
|
1775
|
+
onTabKey(event, item);
|
|
1519
1776
|
}
|
|
1520
1777
|
}, t("tab." + item) + " " + String(view.counts[item]))));
|
|
1521
1778
|
const expiredToggle = snapshot.queue === "pending" ? (0, react.createElement)("button", {
|
|
@@ -1528,14 +1785,19 @@ window.__ModuleLoader__.load({
|
|
|
1528
1785
|
store.toggleExpired();
|
|
1529
1786
|
}
|
|
1530
1787
|
}, t("tab.expired") + " " + String(view.expired)) : null;
|
|
1531
|
-
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", {
|
|
1788
|
+
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", {
|
|
1789
|
+
"data-role": "rows",
|
|
1790
|
+
id: "merge-rows",
|
|
1791
|
+
role: "tabpanel"
|
|
1792
|
+
}, visibleRows.map((row) => rowNode(row, t, copy, sortHandlers, openBody))) : null;
|
|
1532
1793
|
const empty = uiState === "empty" ? (0, react.createElement)("div", null, (0, react.createElement)("p", { "data-role": "note" }, t("empty." + snapshot.queue)), (0, react.createElement)("p", { "data-role": "empty-scope" }, t("empty.scope"))) : null;
|
|
1533
1794
|
const activeFailure = viewFailure !== void 0 ? viewFailure : queue.status === "error" ? queue.failure : void 0;
|
|
1534
1795
|
const overlay = snapshot.overlay;
|
|
1535
1796
|
const menuStyle = menu === void 0 ? void 0 : {
|
|
1536
1797
|
position: "fixed",
|
|
1537
1798
|
zIndex: 70,
|
|
1538
|
-
minWidth: "
|
|
1799
|
+
minWidth: "160px",
|
|
1800
|
+
maxWidth: "min(320px, calc(100vw - 16px))",
|
|
1539
1801
|
left: String(Math.min(menu.x, Math.max(0, (globalThis.innerWidth || 1440) - 180))) + "px",
|
|
1540
1802
|
top: String(Math.min(menu.y, Math.max(0, (globalThis.innerHeight || 800) - 110))) + "px"
|
|
1541
1803
|
};
|
|
@@ -1608,10 +1870,16 @@ window.__ModuleLoader__.load({
|
|
|
1608
1870
|
view,
|
|
1609
1871
|
settings: face.settings,
|
|
1610
1872
|
t
|
|
1611
|
-
}), runNode(view, t, copy), tabs, expiredToggle, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) :
|
|
1873
|
+
}), runNode(view, t, copy), tabs, expiredToggle, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : queue.refreshing === true ? (0, react.createElement)("p", {
|
|
1874
|
+
"data-role": "note",
|
|
1875
|
+
role: "status"
|
|
1876
|
+
}, t("refreshing")) : null, activeFailure === void 0 ? null : failureNode(t, activeFailure, fallback, copy), copyState.kind === "idle" ? null : copyState.kind === "copied" ? (0, react.createElement)("p", {
|
|
1612
1877
|
"data-role": "copied",
|
|
1613
1878
|
role: "status"
|
|
1614
|
-
}, t("copied") + " " +
|
|
1879
|
+
}, t("copied") + " " + (copyState.text ?? "")) : (0, react.createElement)("p", {
|
|
1880
|
+
"data-role": "copy-failed",
|
|
1881
|
+
role: "alert"
|
|
1882
|
+
}, t("copyFailed")), list, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
1615
1883
|
type: "button",
|
|
1616
1884
|
"data-role": "load-more",
|
|
1617
1885
|
disabled: queue.status === "loading",
|
|
@@ -1622,7 +1890,7 @@ window.__ModuleLoader__.load({
|
|
|
1622
1890
|
type: "button",
|
|
1623
1891
|
"data-role": "history",
|
|
1624
1892
|
onClick: () => {
|
|
1625
|
-
|
|
1893
|
+
openHistory();
|
|
1626
1894
|
}
|
|
1627
1895
|
}, t("history")), (0, react.createElement)("button", {
|
|
1628
1896
|
type: "button",
|
|
@@ -1630,11 +1898,7 @@ window.__ModuleLoader__.load({
|
|
|
1630
1898
|
onClick: () => {
|
|
1631
1899
|
copy(doctorCommand);
|
|
1632
1900
|
}
|
|
1633
|
-
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, ()
|
|
1634
|
-
store.closeOverlay();
|
|
1635
|
-
}) : historyNode(overlay, t, () => {
|
|
1636
|
-
store.closeOverlay();
|
|
1637
|
-
}), (0, react.createElement)("button", {
|
|
1901
|
+
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, closeOverlay) : historyNode(overlay, t, closeOverlay), (0, react.createElement)("button", {
|
|
1638
1902
|
type: "button",
|
|
1639
1903
|
"data-role": "refresh",
|
|
1640
1904
|
onClick: () => {
|
|
@@ -1738,7 +2002,11 @@ window.__ModuleLoader__.load({
|
|
|
1738
2002
|
}
|
|
1739
2003
|
async loadView(showLoading = true) {
|
|
1740
2004
|
const token = ++this.viewToken;
|
|
1741
|
-
if (showLoading) this.set({
|
|
2005
|
+
if (showLoading) if (this.snapshot.viewState === "ready") this.set({
|
|
2006
|
+
...this.snapshot,
|
|
2007
|
+
viewRefreshing: true
|
|
2008
|
+
});
|
|
2009
|
+
else this.set({
|
|
1742
2010
|
...this.snapshot,
|
|
1743
2011
|
viewState: "loading",
|
|
1744
2012
|
viewFailure: void 0
|
|
@@ -1765,7 +2033,8 @@ window.__ModuleLoader__.load({
|
|
|
1765
2033
|
this.set({
|
|
1766
2034
|
...this.snapshot,
|
|
1767
2035
|
viewState: "error",
|
|
1768
|
-
viewFailure: outcome.failure
|
|
2036
|
+
viewFailure: outcome.failure,
|
|
2037
|
+
viewRefreshing: false
|
|
1769
2038
|
});
|
|
1770
2039
|
return;
|
|
1771
2040
|
}
|
|
@@ -1774,7 +2043,8 @@ window.__ModuleLoader__.load({
|
|
|
1774
2043
|
...this.snapshot,
|
|
1775
2044
|
view: outcome.payload,
|
|
1776
2045
|
viewState: "ready",
|
|
1777
|
-
viewFailure: void 0
|
|
2046
|
+
viewFailure: void 0,
|
|
2047
|
+
viewRefreshing: false
|
|
1778
2048
|
});
|
|
1779
2049
|
if (wasBlocked && this.snapshot.current.status === "idle") this.loadQueue(this.snapshot.queue, this.snapshot.expiredOnly);
|
|
1780
2050
|
}
|
|
@@ -1783,7 +2053,13 @@ window.__ModuleLoader__.load({
|
|
|
1783
2053
|
const token = (this.tokens.get(key) ?? 0) + 1;
|
|
1784
2054
|
this.tokens.set(key, token);
|
|
1785
2055
|
const previous = this.cache.get(key);
|
|
1786
|
-
const
|
|
2056
|
+
const keepRows = cursor === void 0 && (previous?.rows.length ?? 0) > 0;
|
|
2057
|
+
const next = cursor === void 0 ? keepRows ? {
|
|
2058
|
+
status: "ready",
|
|
2059
|
+
refreshing: true,
|
|
2060
|
+
rows: previous.rows,
|
|
2061
|
+
...previous.nextCursor === void 0 ? {} : { nextCursor: previous.nextCursor }
|
|
2062
|
+
} : {
|
|
1787
2063
|
status: "loading",
|
|
1788
2064
|
rows: []
|
|
1789
2065
|
} : {
|
|
@@ -1815,7 +2091,12 @@ window.__ModuleLoader__.load({
|
|
|
1815
2091
|
});
|
|
1816
2092
|
return;
|
|
1817
2093
|
}
|
|
1818
|
-
const failed = {
|
|
2094
|
+
const failed = keepRows ? {
|
|
2095
|
+
status: "ready",
|
|
2096
|
+
refreshing: false,
|
|
2097
|
+
rows: previous.rows,
|
|
2098
|
+
failure: outcome.failure
|
|
2099
|
+
} : {
|
|
1819
2100
|
status: "error",
|
|
1820
2101
|
rows: [],
|
|
1821
2102
|
failure: outcome.failure
|
|
@@ -1830,6 +2111,7 @@ window.__ModuleLoader__.load({
|
|
|
1830
2111
|
const items = cursor === void 0 ? outcome.payload.items : [...previous?.rows ?? [], ...outcome.payload.items];
|
|
1831
2112
|
const ready = {
|
|
1832
2113
|
status: items.length === 0 ? "empty" : "ready",
|
|
2114
|
+
refreshing: false,
|
|
1833
2115
|
rows: items,
|
|
1834
2116
|
...outcome.payload.nextCursor === void 0 ? {} : { nextCursor: outcome.payload.nextCursor }
|
|
1835
2117
|
};
|
|
@@ -1981,26 +2263,16 @@ window.__ModuleLoader__.load({
|
|
|
1981
2263
|
//#endregion
|
|
1982
2264
|
//#region src/client/index.ts
|
|
1983
2265
|
const inject = ["slots", "locale"];
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
return
|
|
1987
|
-
"aria-hidden": "true",
|
|
1988
|
-
width: String(size),
|
|
1989
|
-
height: String(size),
|
|
1990
|
-
viewBox: "0 0 16 16",
|
|
1991
|
-
fill: "none",
|
|
1992
|
-
stroke: "currentColor",
|
|
1993
|
-
strokeWidth: "1.5",
|
|
1994
|
-
strokeLinecap: "round",
|
|
1995
|
-
strokeLinejoin: "round"
|
|
1996
|
-
}, (0, react.createElement)("path", { d: "M3 4h10M3 8h6M3 12h8" }));
|
|
2266
|
+
/** The view component receives the workbench's activeView marker alongside its face. */
|
|
2267
|
+
function MergeView(props) {
|
|
2268
|
+
return props.activeView === "merge" ? MergePanel(props) : null;
|
|
1997
2269
|
}
|
|
1998
2270
|
/**
|
|
1999
|
-
* Register the merge
|
|
2271
|
+
* Register the merge view on the workbench page.
|
|
2000
2272
|
* @param ctx - the client context.
|
|
2001
2273
|
*/
|
|
2002
2274
|
function apply(ctx) {
|
|
2003
|
-
|
|
2275
|
+
registerWorkbenchView(ctx, {
|
|
2004
2276
|
id: PANEL_ID,
|
|
2005
2277
|
order: 45,
|
|
2006
2278
|
namespace: NS,
|
|
@@ -2012,30 +2284,24 @@ window.__ModuleLoader__.load({
|
|
|
2012
2284
|
css: CSS,
|
|
2013
2285
|
tagId: CSS_TAG_ID
|
|
2014
2286
|
},
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
body: (t) => {
|
|
2287
|
+
component: MergeView,
|
|
2288
|
+
face: (t) => {
|
|
2018
2289
|
const source = {
|
|
2019
2290
|
view,
|
|
2020
2291
|
rows,
|
|
2021
2292
|
body,
|
|
2022
2293
|
history
|
|
2023
2294
|
};
|
|
2024
|
-
|
|
2025
|
-
try {
|
|
2026
|
-
seat = ctx.get?.("configForms");
|
|
2027
|
-
} catch {
|
|
2028
|
-
seat = void 0;
|
|
2029
|
-
}
|
|
2295
|
+
const seat = createSettingsSeat(ctx);
|
|
2030
2296
|
const workspaceId = panelWorkspaceId(ctx);
|
|
2031
2297
|
return {
|
|
2032
2298
|
store: new MergeStore(source),
|
|
2033
2299
|
t,
|
|
2034
2300
|
doctorCommand: "/evolution doctor",
|
|
2035
|
-
settings: {
|
|
2036
|
-
merge: seat.get("evolution-merge"),
|
|
2037
|
-
platform: seat.get("evolution-approval")
|
|
2038
|
-
}
|
|
2301
|
+
settings: {
|
|
2302
|
+
...seat.get("evolution-merge") === void 0 ? {} : { merge: seat.get("evolution-merge") },
|
|
2303
|
+
...seat.get("evolution-approval") === void 0 ? {} : { platform: seat.get("evolution-approval") }
|
|
2304
|
+
},
|
|
2039
2305
|
...workspaceId === void 0 ? {} : { workspaceId }
|
|
2040
2306
|
};
|
|
2041
2307
|
}
|
|
@@ -11,6 +11,8 @@ export interface MergeSource {
|
|
|
11
11
|
export type QueueStatus = 'idle' | 'loading' | 'ready' | 'empty' | 'error';
|
|
12
12
|
export interface QueueState {
|
|
13
13
|
status: QueueStatus;
|
|
14
|
+
/** A background refresh is in flight; the old rows remain visible. */
|
|
15
|
+
refreshing?: boolean | undefined;
|
|
14
16
|
rows: MergeRowView[];
|
|
15
17
|
nextCursor?: string | undefined;
|
|
16
18
|
failure?: MergeFailure | undefined;
|
|
@@ -31,6 +33,7 @@ export type OverlayState = {
|
|
|
31
33
|
export interface StoreSnapshot {
|
|
32
34
|
view: MergeViewPayload;
|
|
33
35
|
viewState: 'loading' | 'ready' | 'error' | 'blocked';
|
|
36
|
+
viewRefreshing?: boolean | undefined;
|
|
34
37
|
viewFailure?: MergeFailure | undefined;
|
|
35
38
|
queue: MergeQueue;
|
|
36
39
|
expiredOnly: boolean;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/** Browser half: one
|
|
1
|
+
/** Browser half: one read-only merge view inside the shared evolution workbench. */
|
|
2
2
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
3
3
|
export declare const inject: string[];
|
|
4
4
|
/**
|
|
5
|
-
* Register the merge
|
|
5
|
+
* Register the merge view on the workbench page.
|
|
6
6
|
* @param ctx - the client context.
|
|
7
7
|
*/
|
|
8
8
|
export declare function apply(ctx: ClientContext): void;
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.32.
|
|
14
|
+
"version": "0.32.6",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"react-dom": "^18.2.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@lmzhen/dsh-evolution-client-kit": "^0.32.
|
|
54
|
+
"@lmzhen/dsh-evolution-client-kit": "^0.32.6"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
57
|
"dsh": ">=0.2.1-rc.2 <0.2.2-0"
|