dsh-continual-evolve 0.14.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/client/client.js +110 -50
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ English | [中文](README.zh.md)
|
|
|
7
7
|
[](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](package.json)
|
|
10
|
-
[]()
|
|
11
11
|
[]()
|
|
12
12
|
[]()
|
|
13
13
|
[]()
|
|
@@ -66,7 +66,7 @@ Profile patch example:
|
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
pnpm install && pnpm build # deps + tsc -> lib/
|
|
69
|
-
pnpm test # vitest (
|
|
69
|
+
pnpm test # vitest (92 tests)
|
|
70
70
|
pnpm test:coverage # v8 coverage, CI-enforced thresholds
|
|
71
71
|
pnpm lint # oxlint src test client
|
|
72
72
|
```
|
package/README.zh.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](package.json)
|
|
10
|
-
[]()
|
|
11
11
|
[]()
|
|
12
12
|
[]()
|
|
13
13
|
[]()
|
|
@@ -66,7 +66,7 @@ profile patch 示例:
|
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
pnpm install && pnpm build # 依赖 + tsc -> lib/
|
|
69
|
-
pnpm test # vitest(
|
|
69
|
+
pnpm test # vitest(92 例)
|
|
70
70
|
pnpm test:coverage # v8 覆盖率,CI 强制阈值
|
|
71
71
|
pnpm lint # oxlint src test client
|
|
72
72
|
```
|
package/client/client.js
CHANGED
|
@@ -76,6 +76,7 @@ window.__ModuleLoader__.load({
|
|
|
76
76
|
var createElement = react.createElement;
|
|
77
77
|
var useState = react.useState;
|
|
78
78
|
var useEffect = react.useEffect;
|
|
79
|
+
var useRef = react.useRef;
|
|
79
80
|
|
|
80
81
|
var NS = "dsh-continual-evolve";
|
|
81
82
|
var SLOT = "plugins.bundle.config";
|
|
@@ -298,6 +299,7 @@ window.__ModuleLoader__.load({
|
|
|
298
299
|
".dce-hint{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:12px;line-height:18px}",
|
|
299
300
|
".dce-empty{border:1px dashed var(--dsw-alias-border-l3,#d1d9e0);border-radius:10px;padding:16px;text-align:center;color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:13px;line-height:20px}",
|
|
300
301
|
".dce-scope-wrap{position:relative;display:inline-flex;min-width:0;max-width:100%;align-self:flex-start}",
|
|
302
|
+
".dce-scope-pill{border-radius:999px}",
|
|
301
303
|
".dce-scope{display:inline-flex;align-items:center;gap:8px;max-width:100%;padding:4px 10px;border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:999px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;font-size:12px;line-height:18px;cursor:pointer}",
|
|
302
304
|
".dce-scope:hover{border-color:var(--dsw-alias-label-dimmed,#c8ccd4)}",
|
|
303
305
|
".dce-scope:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:1px}",
|
|
@@ -307,8 +309,6 @@ window.__ModuleLoader__.load({
|
|
|
307
309
|
".dce-menu-item{display:flex;flex-direction:column;gap:2px;width:100%;padding:6px 10px;border:0;border-radius:8px;background:0 0;font:inherit;color:inherit;text-align:left;cursor:pointer}",
|
|
308
310
|
".dce-menu-item:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.03))}",
|
|
309
311
|
'.dce-menu-item[data-active="true"]{background:var(--dsw-alias-bg-module-platform,#eef1f4)}',
|
|
310
|
-
".dce-menu-label{color:var(--dsw-alias-label-primary,#1f2328);font-size:13px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
311
|
-
".dce-menu-path{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px;line-height:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
312
312
|
".dce-search{width:100%;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l4,#d8dee4);border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-1,#fff);height:32px;color:var(--dsw-alias-label-primary,#1f2328);font:inherit;font-size:12px;padding:0 10px;outline:none}",
|
|
313
313
|
".dce-search::placeholder{color:var(--dsw-alias-label-tertiary,#8b93a1)}",
|
|
314
314
|
".dce-search:focus-visible{border-color:var(--dsw-alias-brand-primary,#4f6ef7)}",
|
|
@@ -321,6 +321,7 @@ window.__ModuleLoader__.load({
|
|
|
321
321
|
".dce-row{display:flex;width:100%;align-items:center;gap:10px;padding:8px 12px;background:0 0;border:0;font:inherit;color:inherit;text-align:left;cursor:pointer}",
|
|
322
322
|
".dce-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.03))}",
|
|
323
323
|
".dce-row:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:-2px}",
|
|
324
|
+
".dce-file-icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;border-radius:8px;background:var(--dsw-alias-bg-module-platform,#eef1f4)}",
|
|
324
325
|
".dce-file-name{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary,#1f2328);font-size:13px;font-weight:500;line-height:18px}",
|
|
325
326
|
".dce-file-time{flex:none;color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px;line-height:16px}",
|
|
326
327
|
".dce-preview{margin:0;padding:8px 12px 10px;background:var(--dsw-alias-bg-module-platform,#eef1f4);border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb)}",
|
|
@@ -369,9 +370,20 @@ window.__ModuleLoader__.load({
|
|
|
369
370
|
var expanded = props.expanded;
|
|
370
371
|
var preview = props.preview;
|
|
371
372
|
var onToggle = props.onToggle;
|
|
372
|
-
var
|
|
373
|
-
|
|
374
|
-
|
|
373
|
+
var UI = props.UI;
|
|
374
|
+
var rowChildren = [];
|
|
375
|
+
if (UI !== null && UI !== undefined && UI.FileIcon !== undefined && UI.FileIcon !== null) {
|
|
376
|
+
// ZCode's memory rows open with a category tile; the host classifies
|
|
377
|
+
// the file itself, so a memory .md gets the markdown glyph.
|
|
378
|
+
rowChildren.push(
|
|
379
|
+
createElement(
|
|
380
|
+
"span",
|
|
381
|
+
{ key: "icon", className: "dce-file-icon" },
|
|
382
|
+
createElement(UI.FileIcon, { path: file.file, size: 16 }),
|
|
383
|
+
),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
rowChildren.push(createElement("span", { key: "name", className: "dce-file-name" }, file.file));
|
|
375
387
|
var time = formatRelative(file.updatedAt, now, t);
|
|
376
388
|
if (time !== "") {
|
|
377
389
|
rowChildren.push(createElement("span", { key: "time", className: "dce-file-time" }, time));
|
|
@@ -409,26 +421,31 @@ window.__ModuleLoader__.load({
|
|
|
409
421
|
return createElement("li", { className: "dce-item" }, children);
|
|
410
422
|
}
|
|
411
423
|
|
|
412
|
-
/**
|
|
413
|
-
function
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
typeof primitives.IconChevronsUpDownOutlineRegular !== "undefined" &&
|
|
418
|
-
primitives.IconChevronsUpDownOutlineRegular !== null
|
|
419
|
-
) {
|
|
420
|
-
return createElement(primitives.IconChevronsUpDownOutlineRegular, { size: 14, "aria-hidden": "true" });
|
|
424
|
+
/** The host's folder marker for a workspace, or nothing on an old host. */
|
|
425
|
+
function FolderMark(props) {
|
|
426
|
+
var UI = props.UI;
|
|
427
|
+
if (UI !== null && UI !== undefined && UI.Folder !== undefined && UI.Folder !== null) {
|
|
428
|
+
return createElement(UI.Folder, { size: 16, "aria-hidden": "true" });
|
|
421
429
|
}
|
|
422
430
|
return null;
|
|
423
431
|
}
|
|
424
432
|
|
|
425
433
|
/**
|
|
426
434
|
* The workspace scope selector, ZCode's Settings → Memory shape: one
|
|
427
|
-
* scope at a time behind a dropdown (
|
|
428
|
-
* label + chevron), never a row of chips
|
|
435
|
+
* scope at a time behind a dropdown (folder marker + current workspace
|
|
436
|
+
* label + chevron), never a row of chips — a chip row can only render
|
|
429
437
|
* when several workspaces are known, so in the common single-workspace
|
|
430
438
|
* case it renders nothing at all and the capability reads as missing.
|
|
431
|
-
*
|
|
439
|
+
*
|
|
440
|
+
* The list is the host's own `Menu` primitive whenever the host provides
|
|
441
|
+
* it: the same surface the rest of the settings UI uses, and it owns
|
|
442
|
+
* outside-click/Escape handling. A hand-rolled document listener gets
|
|
443
|
+
* that wrong — React flushes this component's effect synchronously for
|
|
444
|
+
* the discrete click that opens the list, so a listener attached there
|
|
445
|
+
* catches that very click and closes the list again (the button then
|
|
446
|
+
* looks dead). The hand-rolled list stays as the old-host fallback and
|
|
447
|
+
* closes on a pointerdown outside its wrapper, which cannot be the click
|
|
448
|
+
* that opened it.
|
|
432
449
|
*/
|
|
433
450
|
function WorkspaceScopeMenu(props) {
|
|
434
451
|
var workspaces = props.workspaces;
|
|
@@ -439,27 +456,41 @@ window.__ModuleLoader__.load({
|
|
|
439
456
|
var openState = useState(false);
|
|
440
457
|
var open = openState[0];
|
|
441
458
|
var setOpen = openState[1];
|
|
459
|
+
var wrapRef = useRef(null);
|
|
460
|
+
var hostMenu =
|
|
461
|
+
UI !== null && UI !== undefined && UI.Menu !== undefined && UI.Menu !== null ? UI.Menu : null;
|
|
442
462
|
useEffect(
|
|
443
463
|
function () {
|
|
444
|
-
if (!open || typeof document === "undefined") {
|
|
464
|
+
if (hostMenu !== null || !open || typeof document === "undefined") {
|
|
445
465
|
return undefined;
|
|
446
466
|
}
|
|
447
|
-
var
|
|
448
|
-
|
|
467
|
+
var onPointerDown = function (event) {
|
|
468
|
+
var node = wrapRef.current;
|
|
469
|
+
var target = event.target;
|
|
470
|
+
var inside =
|
|
471
|
+
node !== null &&
|
|
472
|
+
node !== undefined &&
|
|
473
|
+
typeof node.contains === "function" &&
|
|
474
|
+
target !== null &&
|
|
475
|
+
target !== undefined &&
|
|
476
|
+
node.contains(target);
|
|
477
|
+
if (!inside) {
|
|
478
|
+
setOpen(false);
|
|
479
|
+
}
|
|
449
480
|
};
|
|
450
481
|
var onKeyDown = function (event) {
|
|
451
482
|
if (event.key === "Escape") {
|
|
452
|
-
|
|
483
|
+
setOpen(false);
|
|
453
484
|
}
|
|
454
485
|
};
|
|
455
|
-
document.addEventListener("
|
|
486
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
456
487
|
document.addEventListener("keydown", onKeyDown);
|
|
457
488
|
return function () {
|
|
458
|
-
document.removeEventListener("
|
|
489
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
459
490
|
document.removeEventListener("keydown", onKeyDown);
|
|
460
491
|
};
|
|
461
492
|
},
|
|
462
|
-
[open],
|
|
493
|
+
[open, hostMenu],
|
|
463
494
|
);
|
|
464
495
|
var current = null;
|
|
465
496
|
for (var index = 0; index < workspaces.length; index++) {
|
|
@@ -473,18 +504,11 @@ window.__ModuleLoader__.load({
|
|
|
473
504
|
}
|
|
474
505
|
var label = current === null ? "" : current.label || workspaceLabel(current.root);
|
|
475
506
|
var scopeChildren = [
|
|
476
|
-
createElement(ScopeMark, { key: "mark" }),
|
|
477
507
|
createElement("span", { key: "label", className: "dce-scope-label" }, label),
|
|
478
508
|
createElement("span", { key: "caret", className: "dce-scope-caret" }, createElement(Chevron, null)),
|
|
479
509
|
];
|
|
480
|
-
var
|
|
481
|
-
|
|
482
|
-
"aria-haspopup": "menu",
|
|
483
|
-
"aria-expanded": open ? "true" : "false",
|
|
484
|
-
"aria-label": t("scopeLabel"),
|
|
485
|
-
onClick: function () {
|
|
486
|
-
setOpen(!open);
|
|
487
|
-
},
|
|
510
|
+
var toggle = function () {
|
|
511
|
+
setOpen(!open);
|
|
488
512
|
};
|
|
489
513
|
var trigger = null;
|
|
490
514
|
if (UI !== null && UI !== undefined && typeof UI.Button !== "undefined" && UI.Button !== null) {
|
|
@@ -493,12 +517,14 @@ window.__ModuleLoader__.load({
|
|
|
493
517
|
{
|
|
494
518
|
key: "trigger",
|
|
495
519
|
variant: "outline",
|
|
496
|
-
size: "
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
"aria-
|
|
501
|
-
|
|
520
|
+
size: "md",
|
|
521
|
+
icon: createElement(FolderMark, { UI: UI }),
|
|
522
|
+
className: "dce-scope-pill",
|
|
523
|
+
type: "button",
|
|
524
|
+
"aria-haspopup": "menu",
|
|
525
|
+
"aria-expanded": open ? "true" : "false",
|
|
526
|
+
"aria-label": t("scopeLabel"),
|
|
527
|
+
onClick: toggle,
|
|
502
528
|
},
|
|
503
529
|
scopeChildren,
|
|
504
530
|
);
|
|
@@ -507,16 +533,44 @@ window.__ModuleLoader__.load({
|
|
|
507
533
|
"button",
|
|
508
534
|
{
|
|
509
535
|
key: "trigger",
|
|
510
|
-
type:
|
|
536
|
+
type: "button",
|
|
511
537
|
className: "dce-scope",
|
|
512
|
-
"aria-haspopup":
|
|
513
|
-
"aria-expanded":
|
|
514
|
-
"aria-label":
|
|
515
|
-
onClick:
|
|
538
|
+
"aria-haspopup": "menu",
|
|
539
|
+
"aria-expanded": open ? "true" : "false",
|
|
540
|
+
"aria-label": t("scopeLabel"),
|
|
541
|
+
onClick: toggle,
|
|
516
542
|
},
|
|
517
543
|
scopeChildren,
|
|
518
544
|
);
|
|
519
545
|
}
|
|
546
|
+
if (hostMenu !== null) {
|
|
547
|
+
return createElement(hostMenu, {
|
|
548
|
+
key: "scope",
|
|
549
|
+
open: open,
|
|
550
|
+
anchor: trigger,
|
|
551
|
+
items: workspaces.map(function (workspace) {
|
|
552
|
+
return {
|
|
553
|
+
id: workspace.root,
|
|
554
|
+
label: workspace.label || workspaceLabel(workspace.root),
|
|
555
|
+
icon: createElement(FolderMark, { UI: UI }),
|
|
556
|
+
};
|
|
557
|
+
}),
|
|
558
|
+
selectedId: selected,
|
|
559
|
+
onSelect: function (id) {
|
|
560
|
+
setOpen(false);
|
|
561
|
+
if (id !== selected) {
|
|
562
|
+
onSelect(id);
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
onClose: function () {
|
|
566
|
+
setOpen(false);
|
|
567
|
+
},
|
|
568
|
+
align: "start",
|
|
569
|
+
side: "bottom",
|
|
570
|
+
portal: true,
|
|
571
|
+
selection: "check",
|
|
572
|
+
});
|
|
573
|
+
}
|
|
520
574
|
var menu = null;
|
|
521
575
|
if (open) {
|
|
522
576
|
menu = createElement(
|
|
@@ -539,15 +593,12 @@ window.__ModuleLoader__.load({
|
|
|
539
593
|
}
|
|
540
594
|
},
|
|
541
595
|
},
|
|
542
|
-
|
|
543
|
-
// disambiguates two workspaces that read the same.
|
|
544
|
-
createElement("span", { key: "label", className: "dce-menu-label" }, workspace.label || workspaceLabel(workspace.root)),
|
|
545
|
-
createElement("span", { key: "root", className: "dce-menu-path" }, workspace.root),
|
|
596
|
+
workspace.label || workspaceLabel(workspace.root),
|
|
546
597
|
);
|
|
547
598
|
}),
|
|
548
599
|
);
|
|
549
600
|
}
|
|
550
|
-
return createElement("div", { key: "scope", className: "dce-scope-wrap" }, trigger, menu);
|
|
601
|
+
return createElement("div", { key: "scope", className: "dce-scope-wrap", ref: wrapRef }, trigger, menu);
|
|
551
602
|
}
|
|
552
603
|
|
|
553
604
|
/** One workspace's memory store: stats, drift warnings, searchable file list with previews. */
|
|
@@ -669,6 +720,7 @@ window.__ModuleLoader__.load({
|
|
|
669
720
|
file: file,
|
|
670
721
|
now: now,
|
|
671
722
|
t: t,
|
|
723
|
+
UI: UI,
|
|
672
724
|
expanded: expandedFile === file.file,
|
|
673
725
|
preview: preview,
|
|
674
726
|
onToggle: function () {
|
|
@@ -896,7 +948,15 @@ window.__ModuleLoader__.load({
|
|
|
896
948
|
}
|
|
897
949
|
var UI = null;
|
|
898
950
|
if (primitives !== undefined && primitives !== null && typeof primitives.Button !== "undefined") {
|
|
899
|
-
|
|
951
|
+
// The scope selector prefers the host's own Menu and folder icon;
|
|
952
|
+
// each stays optional so a host with only Button still gets the
|
|
953
|
+
// hand-rolled list and a plain trigger.
|
|
954
|
+
UI = {
|
|
955
|
+
Button: primitives.Button,
|
|
956
|
+
Menu: primitives.Menu,
|
|
957
|
+
Folder: primitives.IconFolderOpenOutlineRegular,
|
|
958
|
+
FileIcon: primitives.FileTypeIcon,
|
|
959
|
+
};
|
|
900
960
|
}
|
|
901
961
|
ctx.slots.inject(SLOT, function () {
|
|
902
962
|
return ctx.slots.register(
|
package/package.json
CHANGED