@lmzhen/dsh-evolution-merge-ui 0.29.0 → 0.30.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 CHANGED
@@ -31,8 +31,8 @@ window.__ModuleLoader__.load({
31
31
  merge: {
32
32
  view: "/api/dsh-evolution/merge/view",
33
33
  rows: "/api/dsh-evolution/merge/rows",
34
- run: "/api/dsh-evolution/merge/run",
35
- runs: "/api/dsh-evolution/merge/runs"
34
+ body: "/api/dsh-evolution/merge/body",
35
+ history: "/api/dsh-evolution/merge/history"
36
36
  },
37
37
  diagnostics: { view: "/api/dsh-evolution/diagnostics" }
38
38
  };
@@ -158,11 +158,15 @@ window.__ModuleLoader__.load({
158
158
  const zh = {
159
159
  "entry.label": "技能合并",
160
160
  "hint": "手动触发;后台逐对判定。这里只读,不写技能。",
161
+ "history": "历史",
162
+ "close": "关闭",
163
+ "tab.verify": "待判断",
161
164
  "tab.pending": "待批准",
162
- "tab.retry": "待重跑",
165
+ "tab.fuse": "待合并",
163
166
  "tab.skipped": "无需合并",
167
+ "empty.verify": "没有待判断的对。",
164
168
  "empty.pending": "没有待批准的合并。",
165
- "empty.retry": "没有待重跑的对。",
169
+ "empty.fuse": "没有待合并的对。",
166
170
  "empty.skipped": "没有标记为无需合并的对。",
167
171
  "loading": "正在读取…",
168
172
  "refresh": "刷新",
@@ -179,6 +183,8 @@ window.__ModuleLoader__.load({
179
183
  "row.attempts": "尝试",
180
184
  "row.origin": "来源",
181
185
  "row.expires": "暂存到期",
186
+ "row.expired": "已过期",
187
+ "row.reason": "原因",
182
188
  "row.failure": "失败",
183
189
  "row.noRetry": "不可重试",
184
190
  "row.copy": "复制命令",
@@ -186,17 +192,22 @@ window.__ModuleLoader__.load({
186
192
  "origin.human": "人工",
187
193
  "state.verify": "待判定",
188
194
  "state.pending": "待批准",
189
- "state.fuse": "待融合",
195
+ "state.approved": "已批准",
196
+ "state.fuse": "待合并",
190
197
  "state.skipped": "已跳过"
191
198
  };
192
199
  const en = {
193
200
  "entry.label": "Skill merge",
194
201
  "hint": "Manual only; pairs are judged in the background. Read-only here.",
195
- "tab.pending": "Pending",
196
- "tab.retry": "Retry",
202
+ "history": "History",
203
+ "close": "Close",
204
+ "tab.verify": "To judge",
205
+ "tab.pending": "Pending approval",
206
+ "tab.fuse": "Ready to merge",
197
207
  "tab.skipped": "Skipped",
208
+ "empty.verify": "No pairs to judge.",
198
209
  "empty.pending": "No pending merges.",
199
- "empty.retry": "No pairs waiting to retry.",
210
+ "empty.fuse": "No pairs ready to merge.",
200
211
  "empty.skipped": "No pairs marked as not worth merging.",
201
212
  "loading": "Loading…",
202
213
  "refresh": "Refresh",
@@ -213,6 +224,8 @@ window.__ModuleLoader__.load({
213
224
  "row.attempts": "Attempts",
214
225
  "row.origin": "Origin",
215
226
  "row.expires": "Staging expires",
227
+ "row.expired": "Expired",
228
+ "row.reason": "Reason",
216
229
  "row.failure": "Failure",
217
230
  "row.noRetry": "not retryable",
218
231
  "row.copy": "Copy command",
@@ -220,7 +233,8 @@ window.__ModuleLoader__.load({
220
233
  "origin.human": "human",
221
234
  "state.verify": "Unverified",
222
235
  "state.pending": "Pending approval",
223
- "state.fuse": "Ready to fuse",
236
+ "state.approved": "Approved",
237
+ "state.fuse": "Ready to merge",
224
238
  "state.skipped": "Skipped"
225
239
  };
226
240
  //#endregion
@@ -297,8 +311,9 @@ window.__ModuleLoader__.load({
297
311
  * intentionally copied commands, not buttons that write from the browser.
298
312
  */
299
313
  const QUEUES = [
314
+ "verify",
300
315
  "pending",
301
- "retry",
316
+ "fuse",
302
317
  "skipped"
303
318
  ];
304
319
  function failure(t, failure) {
@@ -316,6 +331,7 @@ window.__ModuleLoader__.load({
316
331
  const [loading, setLoading] = (0, react.useState)(face.loadRows !== void 0 || face.loadView !== void 0);
317
332
  const [failed, setFailed] = (0, react.useState)(void 0);
318
333
  const [nextCursor, setNextCursor] = (0, react.useState)(void 0);
334
+ const [overlay, setOverlay] = (0, react.useState)(void 0);
319
335
  const request = (0, react.useRef)(0);
320
336
  const loadRows = (queue, cursor = 0) => {
321
337
  const load = face.loadRows;
@@ -347,7 +363,7 @@ window.__ModuleLoader__.load({
347
363
  setFailed(outcome.failure);
348
364
  return;
349
365
  }
350
- if (outcome.payload.schemaVersion !== void 0 && outcome.payload.schemaVersion !== 1) {
366
+ if (outcome.payload.schemaVersion !== void 0 && outcome.payload.schemaVersion !== 2) {
351
367
  setFailed({
352
368
  kind: "server",
353
369
  status: 0
@@ -362,6 +378,39 @@ window.__ModuleLoader__.load({
362
378
  });
363
379
  });
364
380
  };
381
+ const openBody = (id, side) => {
382
+ const load = face.loadBody;
383
+ if (load === void 0) return;
384
+ load(id, side).then((outcome) => {
385
+ if (outcome.ok) setOverlay({
386
+ kind: "body",
387
+ html: outcome.payload.html,
388
+ label: id + ":" + side
389
+ });
390
+ else setFailed(outcome.failure);
391
+ }).catch(() => {
392
+ setFailed({
393
+ kind: "server",
394
+ status: 0
395
+ });
396
+ });
397
+ };
398
+ const openHistory = () => {
399
+ const load = face.loadHistory;
400
+ if (load === void 0) return;
401
+ load().then((outcome) => {
402
+ if (outcome.ok) setOverlay({
403
+ kind: "history",
404
+ items: outcome.payload.items
405
+ });
406
+ else setFailed(outcome.failure);
407
+ }).catch(() => {
408
+ setFailed({
409
+ kind: "server",
410
+ status: 0
411
+ });
412
+ });
413
+ };
365
414
  (0, react.useEffect)(() => {
366
415
  loadView();
367
416
  loadRows("pending");
@@ -399,12 +448,27 @@ window.__ModuleLoader__.load({
399
448
  row.attempts === void 0 ? void 0 : t("row.attempts") + " " + String(row.attempts),
400
449
  row.origin === void 0 ? void 0 : t("row.origin") + " " + t("origin." + row.origin),
401
450
  row.stagingExpiresAt === void 0 ? void 0 : t("row.expires") + " " + new Date(row.stagingExpiresAt).toLocaleString(),
451
+ row.expired === void 0 ? void 0 : t("row.expired") + " " + row.expired,
452
+ row.reason === void 0 ? void 0 : t("row.reason") + " " + row.reason,
453
+ row.summary === void 0 ? void 0 : row.summary.filter(Boolean).join(" · "),
402
454
  row.failure === void 0 ? void 0 : t("row.failure") + " " + row.failure.message + (row.failure.retryable ? "" : " · " + t("row.noRetry"))
403
455
  ].filter((value) => value !== void 0).join(" · ");
404
456
  return (0, react.createElement)("div", {
405
457
  key: row.id,
406
458
  "data-role": "row"
407
- }, (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-label" }, row.label), (0, react.createElement)("div", { "data-role": "row-meta" }, t("state." + row.state) + (row.stage === null ? "" : " · " + t("stage." + row.stage))), facts === "" ? null : (0, react.createElement)("div", { "data-role": "row-facts" }, facts)), (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-meta" }, row.updatedAt), (0, react.createElement)("div", { "data-role": "row-actions" }, (row.actions ?? []).filter((action) => view.approval !== false || !action.includes("/evolution merge approve")).map((action) => (0, react.createElement)("button", {
459
+ }, (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-label" }, row.label), (0, react.createElement)("div", { "data-role": "row-meta" }, t("state." + row.state) + (row.stage === null ? "" : " · " + t("stage." + row.stage))), facts === "" ? null : (0, react.createElement)("div", { "data-role": "row-facts" }, facts)), (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-meta" }, row.updatedAt), (0, react.createElement)("div", { "data-role": "row-actions" }, face.loadBody === void 0 ? null : (0, react.createElement)("button", {
460
+ type: "button",
461
+ "data-role": "body-a",
462
+ onClick: () => {
463
+ openBody(row.id, "a");
464
+ }
465
+ }, "A"), face.loadBody === void 0 ? null : (0, react.createElement)("button", {
466
+ type: "button",
467
+ "data-role": "body-b",
468
+ onClick: () => {
469
+ openBody(row.id, "b");
470
+ }
471
+ }, "B"), (row.actions ?? []).filter((action) => view.approval !== false || !action.includes("/evolution merge approve")).map((action) => (0, react.createElement)("button", {
408
472
  key: action,
409
473
  type: "button",
410
474
  "data-role": "row-action",
@@ -423,7 +487,21 @@ window.__ModuleLoader__.load({
423
487
  onClick: () => {
424
488
  loadRows(tab, Number(nextCursor));
425
489
  }
426
- }, t("loadMore")), (0, react.createElement)("button", {
490
+ }, t("loadMore")), face.loadHistory === void 0 ? null : (0, react.createElement)("button", {
491
+ type: "button",
492
+ "data-role": "history",
493
+ onClick: openHistory
494
+ }, t("history")), overlay === void 0 ? null : (0, react.createElement)("section", { "data-role": "overlay" }, (0, react.createElement)("button", {
495
+ type: "button",
496
+ "data-role": "overlay-close",
497
+ onClick: () => {
498
+ setOverlay(void 0);
499
+ }
500
+ }, t("close")), overlay.kind === "body" ? (0, react.createElement)("div", {
501
+ "data-role": "body",
502
+ "data-label": overlay.label,
503
+ dangerouslySetInnerHTML: { __html: overlay.html }
504
+ }) : (0, react.createElement)("ul", { "data-role": "history-list" }, overlay.items.map((item) => (0, react.createElement)("li", { key: item.name }, item.name + " · " + item.kind + " · " + item.reason + " · v" + String(item.lastVersion))))), (0, react.createElement)("button", {
427
505
  type: "button",
428
506
  "data-role": "refresh",
429
507
  onClick: () => {
@@ -452,17 +530,22 @@ window.__ModuleLoader__.load({
452
530
  function seedView() {
453
531
  return {
454
532
  counts: {
533
+ verify: 0,
455
534
  pending: 0,
456
- retry: 0,
535
+ fuse: 0,
457
536
  skipped: 0
458
537
  },
459
538
  tabs: [
539
+ {
540
+ queue: "verify",
541
+ count: 0
542
+ },
460
543
  {
461
544
  queue: "pending",
462
545
  count: 0
463
546
  },
464
547
  {
465
- queue: "retry",
548
+ queue: "fuse",
466
549
  count: 0
467
550
  },
468
551
  {
@@ -3,12 +3,16 @@
3
3
  * intentionally copied commands, not buttons that write from the browser.
4
4
  */
5
5
  import { type ReactNode } from 'react';
6
- import type { MergeOutcome, MergeQueue, MergeRowView, MergeViewPayload, QueuePage } from './api.ts';
6
+ import type { MergeBody, MergeHistoryItem, MergeOutcome, MergeQueue, MergeRowView, MergeViewPayload, QueuePage } from './api.ts';
7
7
  export interface MergeFace {
8
8
  view: MergeViewPayload;
9
9
  rows: MergeRowView[];
10
10
  loadView?: () => Promise<MergeOutcome<MergeViewPayload>>;
11
11
  loadRows?: (queue: MergeQueue, cursor?: number) => Promise<MergeOutcome<QueuePage>>;
12
+ loadBody?: (id: string, side: 'a' | 'b') => Promise<MergeOutcome<MergeBody>>;
13
+ loadHistory?: () => Promise<MergeOutcome<{
14
+ items: MergeHistoryItem[];
15
+ }>>;
12
16
  t: (key: string) => string;
13
17
  }
14
18
  export declare function MergePanel(face: MergeFace): ReactNode;
@@ -2,13 +2,14 @@ import { type RouteFailure } from './route-client.generated.ts';
2
2
  export declare const HOST_ROUTES: {
3
3
  readonly view: "/api/dsh-evolution/merge/view";
4
4
  readonly rows: "/api/dsh-evolution/merge/rows";
5
- readonly run: "/api/dsh-evolution/merge/run";
6
- readonly runs: "/api/dsh-evolution/merge/runs";
5
+ readonly body: "/api/dsh-evolution/merge/body";
6
+ readonly history: "/api/dsh-evolution/merge/history";
7
7
  };
8
- export type MergeQueue = 'pending' | 'retry' | 'skipped';
8
+ export type MergeQueue = 'verify' | 'pending' | 'fuse' | 'skipped';
9
9
  export interface MergeCounts {
10
+ verify: number;
10
11
  pending: number;
11
- retry: number;
12
+ fuse: number;
12
13
  skipped: number;
13
14
  }
14
15
  export interface MergeRunView {
@@ -55,6 +56,9 @@ export interface MergeRowView {
55
56
  attempts?: number;
56
57
  origin?: 'agent' | 'human';
57
58
  stagingExpiresAt?: number;
59
+ expired?: 'target-taken' | 'source-changed';
60
+ reason?: string;
61
+ summary?: string[];
58
62
  actions?: string[];
59
63
  }
60
64
  export interface QueuePage {
@@ -62,6 +66,19 @@ export interface QueuePage {
62
66
  items: MergeRowView[];
63
67
  nextCursor?: string;
64
68
  }
69
+ export interface MergeBody {
70
+ content: string;
71
+ markdown: boolean;
72
+ html: string;
73
+ }
74
+ export interface MergeHistoryItem {
75
+ name: string;
76
+ kind: 'merged' | 'deleted' | 'split' | 'other';
77
+ reason: string;
78
+ lastVersion: number;
79
+ archivedAt: string;
80
+ sourceRunId?: string;
81
+ }
65
82
  export type MergeOutcome<T> = {
66
83
  ok: true;
67
84
  payload: T;
@@ -71,4 +88,8 @@ export type MergeOutcome<T> = {
71
88
  };
72
89
  export declare function view(): Promise<MergeOutcome<MergeViewPayload>>;
73
90
  export declare function rows(queue: MergeQueue, cursor?: number): Promise<MergeOutcome<QueuePage>>;
91
+ export declare function body(id: string, side: 'a' | 'b'): Promise<MergeOutcome<MergeBody>>;
92
+ export declare function history(): Promise<MergeOutcome<{
93
+ items: MergeHistoryItem[];
94
+ }>>;
74
95
  //# sourceMappingURL=api.d.ts.map
@@ -27,8 +27,8 @@ export declare const ROUTES: {
27
27
  readonly merge: {
28
28
  readonly view: "/api/dsh-evolution/merge/view";
29
29
  readonly rows: "/api/dsh-evolution/merge/rows";
30
- readonly run: "/api/dsh-evolution/merge/run";
31
- readonly runs: "/api/dsh-evolution/merge/runs";
30
+ readonly body: "/api/dsh-evolution/merge/body";
31
+ readonly history: "/api/dsh-evolution/merge/history";
32
32
  };
33
33
  readonly diagnostics: {
34
34
  readonly view: "/api/dsh-evolution/diagnostics";
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ]
12
12
  }
13
13
  },
14
- "version": "0.29.0",
14
+ "version": "0.30.0",
15
15
  "publishConfig": {
16
16
  "access": "public"
17
17
  },