@morehao/dsh-skills-console 0.3.7 → 0.3.8
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/client.js +304 -243
- package/package.json +3 -2
package/client.js
CHANGED
|
@@ -848,7 +848,26 @@ function FolderIcon({ size = 12 }) {
|
|
|
848
848
|
}
|
|
849
849
|
|
|
850
850
|
// client/section.js
|
|
851
|
-
var
|
|
851
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
852
|
+
|
|
853
|
+
// client/scroll.js
|
|
854
|
+
function isScroller(node, tolerance = 4) {
|
|
855
|
+
if (!node || typeof getComputedStyle !== "function") return false;
|
|
856
|
+
const style = getComputedStyle(node);
|
|
857
|
+
return Boolean(style && /(auto|scroll)/.test(style.overflowY || "") && node.scrollHeight > node.clientHeight + tolerance);
|
|
858
|
+
}
|
|
859
|
+
function nearestScroller(node, tolerance = 4) {
|
|
860
|
+
let current = node?.parentElement || null;
|
|
861
|
+
while (current) {
|
|
862
|
+
if (isScroller(current, tolerance)) return current;
|
|
863
|
+
current = current.parentElement || null;
|
|
864
|
+
}
|
|
865
|
+
return typeof document !== "undefined" ? document.scrollingElement || null : null;
|
|
866
|
+
}
|
|
867
|
+
function scrollHost(node, tolerance = 4) {
|
|
868
|
+
if (isScroller(node, tolerance)) return node;
|
|
869
|
+
return node && nearestScroller(node, tolerance) || node;
|
|
870
|
+
}
|
|
852
871
|
|
|
853
872
|
// client/styles.js
|
|
854
873
|
var CSS = `
|
|
@@ -1267,8 +1286,9 @@ var CSS = `
|
|
|
1267
1286
|
color: var(--dsw-alias-label-secondary); line-height: 1.6; }
|
|
1268
1287
|
.dshsc-reader-placeholder b { color: var(--dsw-alias-label-primary); font-size: 13px; }
|
|
1269
1288
|
|
|
1270
|
-
/* 文件 tab
|
|
1271
|
-
.dshsc-reader-files { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
|
|
1289
|
+
/* 文件 tab:抽屉里上下排;整页(宽容器)左树右预览 */
|
|
1290
|
+
.dshsc-reader-files { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; align-items: start; }
|
|
1291
|
+
.dshsc-reader-page .dshsc-reader-files { grid-template-columns: minmax(200px, 240px) minmax(0, 1fr); }
|
|
1272
1292
|
.dshsc-reader-tree { border: 1px solid var(--dsw-alias-border-l1); border-radius: 10px; overflow: auto;
|
|
1273
1293
|
max-height: 300px; background: var(--dsw-alias-bg-layer-1); }
|
|
1274
1294
|
.dshsc-reader-preview { border: 1px solid var(--dsw-alias-border-l1); border-radius: 10px; overflow: hidden;
|
|
@@ -1386,8 +1406,11 @@ var CSS = `
|
|
|
1386
1406
|
background: var(--dsw-alias-bg-layer-1); }
|
|
1387
1407
|
.dshsc-reader-hero .dshsc-reader-head { border-bottom: 0; }
|
|
1388
1408
|
.dshsc-reader-hero .dshsc-reader-desc { -webkit-line-clamp: 3; max-width: 78ch; }
|
|
1389
|
-
.dshsc-reader-layout { flex: 1; min-height: 0; display: grid; grid-template-columns:
|
|
1409
|
+
.dshsc-reader-layout { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr);
|
|
1390
1410
|
gap: 18px; align-items: stretch; }
|
|
1411
|
+
/* 只有目录真的在的时候才开第二轨:否则唯一的正文列会被自动摆进 180px 的目录轨,
|
|
1412
|
+
文件 / 信息 tab 会窄成一条(树里的文件名被截断、预览挤到下面)。 */
|
|
1413
|
+
.dshsc-reader-layout.has-toc { grid-template-columns: 180px minmax(0, 1fr); }
|
|
1391
1414
|
.dshsc-reader-toc { position: sticky; top: 0; display: flex; flex-direction: column; gap: 1px;
|
|
1392
1415
|
max-height: 70vh; overflow: auto; padding-right: 4px; }
|
|
1393
1416
|
.dshsc-reader-toc-title { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
|
|
@@ -1413,11 +1436,20 @@ var CSS = `
|
|
|
1413
1436
|
@container dshsc (max-width: 860px) {
|
|
1414
1437
|
/* 行内「查看」先让位:技能名本身仍是入口 */
|
|
1415
1438
|
.dshsc-row .dshsc-view { display: none; }
|
|
1416
|
-
.dshsc-reader-layout { grid-template-columns: minmax(0, 1fr); }
|
|
1439
|
+
.dshsc-reader-layout.has-toc { grid-template-columns: minmax(0, 1fr); }
|
|
1440
|
+
.dshsc-reader-page .dshsc-reader-files { grid-template-columns: minmax(0, 1fr); }
|
|
1417
1441
|
.dshsc-reader-toc { display: none; }
|
|
1418
1442
|
.dshsc-reader-page .dshsc-reader-desc { -webkit-line-clamp: 2; }
|
|
1419
1443
|
}
|
|
1420
1444
|
|
|
1445
|
+
/* 描述默认按行数截断;真被截断时下面给「展开 / 收起」,所以要压在上面所有 clamp 规则之后 */
|
|
1446
|
+
.dshsc-reader-descblock { display: flex; flex-direction: column; align-items: flex-start; }
|
|
1447
|
+
.dshsc-reader-desc.expanded { display: block; overflow: visible; -webkit-line-clamp: unset; }
|
|
1448
|
+
.dshsc-reader-more { margin-top: 3px; padding: 0; border: 0; border-radius: 4px; background: transparent;
|
|
1449
|
+
color: var(--dsw-alias-brand-primary); font: inherit; font-size: 11.5px; line-height: 1.6; cursor: pointer; }
|
|
1450
|
+
.dshsc-reader-more:hover { text-decoration: underline; }
|
|
1451
|
+
.dshsc-reader-more:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 2px; }
|
|
1452
|
+
|
|
1421
1453
|
.dshsc-toast { position: fixed; right: 18px; bottom: 18px; z-index: 70; font-size: 12px; padding: 10px 13px; border-radius: 9px;
|
|
1422
1454
|
background: var(--dsw-alias-bg-layer-3); color: var(--dsw-alias-label-primary); border: 1px solid var(--dsw-alias-border-l2);
|
|
1423
1455
|
box-shadow: 0 8px 24px rgba(0,0,0,.22); max-width: 420px; }
|
|
@@ -2447,7 +2479,12 @@ function SubscriptionsTab({
|
|
|
2447
2479
|
}
|
|
2448
2480
|
|
|
2449
2481
|
// client/views/modals.js
|
|
2482
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
2483
|
+
|
|
2484
|
+
// client/views/add-skill.js
|
|
2450
2485
|
var import_react3 = __toESM(require("react"), 1);
|
|
2486
|
+
|
|
2487
|
+
// client/views/overlay.js
|
|
2451
2488
|
function Overlay({ t, title, children, footer, onCancel }) {
|
|
2452
2489
|
useOverlayLayer(true, onCancel);
|
|
2453
2490
|
return portalize(h(
|
|
@@ -2472,8 +2509,152 @@ function Overlay({ t, title, children, footer, onCancel }) {
|
|
|
2472
2509
|
)
|
|
2473
2510
|
), overlayHost());
|
|
2474
2511
|
}
|
|
2512
|
+
|
|
2513
|
+
// client/views/add-skill.js
|
|
2514
|
+
function AddSkillModal({ t, onCancel, onProbe, onInstall }) {
|
|
2515
|
+
const [source, setSource] = import_react3.default.useState("");
|
|
2516
|
+
const [phase, setPhase] = import_react3.default.useState("idle");
|
|
2517
|
+
const [options, setOptions] = import_react3.default.useState([]);
|
|
2518
|
+
const [selected, setSelected] = import_react3.default.useState(() => /* @__PURE__ */ new Set());
|
|
2519
|
+
const [manual, setManual] = import_react3.default.useState("");
|
|
2520
|
+
const [skipped, setSkipped] = import_react3.default.useState(0);
|
|
2521
|
+
const [error, setError] = import_react3.default.useState(null);
|
|
2522
|
+
const reset = (value) => {
|
|
2523
|
+
setSource(value);
|
|
2524
|
+
setPhase("idle");
|
|
2525
|
+
setOptions([]);
|
|
2526
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
2527
|
+
setSkipped(0);
|
|
2528
|
+
setError(null);
|
|
2529
|
+
};
|
|
2530
|
+
const probe = async () => {
|
|
2531
|
+
const value = source.trim();
|
|
2532
|
+
if (!value || phase === "probing") return;
|
|
2533
|
+
setPhase("probing");
|
|
2534
|
+
setError(null);
|
|
2535
|
+
try {
|
|
2536
|
+
const result = await onProbe(value);
|
|
2537
|
+
const found = Array.isArray(result?.skills) ? result.skills : [];
|
|
2538
|
+
setOptions(found);
|
|
2539
|
+
setSelected(new Set(found.map((item) => item.name)));
|
|
2540
|
+
setSkipped(Math.max(0, Number(result?.skipped) || 0));
|
|
2541
|
+
setPhase(found.length > 0 ? "picked" : "empty");
|
|
2542
|
+
} catch (err) {
|
|
2543
|
+
setError(err?.message || String(err));
|
|
2544
|
+
setPhase("failed");
|
|
2545
|
+
}
|
|
2546
|
+
};
|
|
2547
|
+
const toggle = (name) => setSelected((prev) => {
|
|
2548
|
+
const next = new Set(prev);
|
|
2549
|
+
if (next.has(name)) next.delete(name);
|
|
2550
|
+
else next.add(name);
|
|
2551
|
+
return next;
|
|
2552
|
+
});
|
|
2553
|
+
const names = manual.split(/[,,\s]+/).map((item) => item.trim()).filter(Boolean);
|
|
2554
|
+
const skippedText = skipped > 0 ? t("form.skipped").replace("{n}", String(skipped)) : null;
|
|
2555
|
+
const manualMode = phase === "empty" || phase === "failed";
|
|
2556
|
+
const skills = phase === "picked" ? [...selected] : names;
|
|
2557
|
+
const canSubmit = phase === "picked" ? selected.size > 0 : manualMode ? names.length > 0 : false;
|
|
2558
|
+
const submit = () => {
|
|
2559
|
+
if (!canSubmit) return;
|
|
2560
|
+
onInstall({ source: source.trim(), skills });
|
|
2561
|
+
};
|
|
2562
|
+
return h(
|
|
2563
|
+
Overlay,
|
|
2564
|
+
{
|
|
2565
|
+
t,
|
|
2566
|
+
title: t("action.addSkill"),
|
|
2567
|
+
onCancel,
|
|
2568
|
+
footer: [
|
|
2569
|
+
h("button", { key: "c", className: "dshsc-btn ghost", onClick: onCancel }, t("action.cancel")),
|
|
2570
|
+
h("button", {
|
|
2571
|
+
key: "s",
|
|
2572
|
+
className: "dshsc-btn primary",
|
|
2573
|
+
disabled: !canSubmit,
|
|
2574
|
+
onClick: submit
|
|
2575
|
+
}, t("action.save"))
|
|
2576
|
+
]
|
|
2577
|
+
},
|
|
2578
|
+
h("p", { className: "dshsc-sub" }, t("form.pickHint")),
|
|
2579
|
+
h(
|
|
2580
|
+
"div",
|
|
2581
|
+
{ className: "dshsc-field" },
|
|
2582
|
+
h("span", null, t("form.source")),
|
|
2583
|
+
h(
|
|
2584
|
+
"div",
|
|
2585
|
+
{ className: "dshsc-inline" },
|
|
2586
|
+
h("input", {
|
|
2587
|
+
value: source,
|
|
2588
|
+
placeholder: t("form.sourceHint"),
|
|
2589
|
+
onChange: (event) => reset(event.target.value),
|
|
2590
|
+
onKeyDown: (event) => {
|
|
2591
|
+
if (event.key === "Enter") void probe();
|
|
2592
|
+
}
|
|
2593
|
+
}),
|
|
2594
|
+
h("button", {
|
|
2595
|
+
className: "dshsc-btn",
|
|
2596
|
+
disabled: !source.trim() || phase === "probing",
|
|
2597
|
+
onClick: () => void probe()
|
|
2598
|
+
}, phase === "probing" ? t("form.probing") : t("form.probe"))
|
|
2599
|
+
)
|
|
2600
|
+
),
|
|
2601
|
+
phase === "picked" ? h(
|
|
2602
|
+
"div",
|
|
2603
|
+
{ key: "picked" },
|
|
2604
|
+
h("div", { className: "dshsc-group" }, t("form.detected").replace("{n}", String(options.length))),
|
|
2605
|
+
h(
|
|
2606
|
+
"div",
|
|
2607
|
+
{ style: { display: "flex", gap: 6, marginBottom: 6 } },
|
|
2608
|
+
h("button", {
|
|
2609
|
+
className: "dshsc-btn ghost",
|
|
2610
|
+
onClick: () => setSelected(new Set(options.map((item) => item.name)))
|
|
2611
|
+
}, t("form.selectAll")),
|
|
2612
|
+
h("button", {
|
|
2613
|
+
className: "dshsc-btn ghost",
|
|
2614
|
+
onClick: () => setSelected(/* @__PURE__ */ new Set())
|
|
2615
|
+
}, t("form.selectNone"))
|
|
2616
|
+
),
|
|
2617
|
+
h("div", { className: "dshsc-panel" }, options.map((option) => h(
|
|
2618
|
+
"label",
|
|
2619
|
+
{ className: "dshsc-check dshsc-skill", key: option.name },
|
|
2620
|
+
h("input", {
|
|
2621
|
+
type: "checkbox",
|
|
2622
|
+
checked: selected.has(option.name),
|
|
2623
|
+
onChange: () => toggle(option.name)
|
|
2624
|
+
}),
|
|
2625
|
+
h(
|
|
2626
|
+
"span",
|
|
2627
|
+
{ className: "dshsc-skill-main" },
|
|
2628
|
+
h("span", { className: "dshsc-skill-name" }, option.name),
|
|
2629
|
+
option.description ? h("small", { className: "dshsc-skill-desc" }, option.description) : null,
|
|
2630
|
+
h("small", { className: "dshsc-skill-path" }, option.skillPath)
|
|
2631
|
+
)
|
|
2632
|
+
))),
|
|
2633
|
+
skippedText ? h("p", { className: "dshsc-sub" }, skippedText) : null
|
|
2634
|
+
) : null,
|
|
2635
|
+
phase === "probing" ? h("p", { className: "dshsc-sub" }, t("form.probingHint")) : null,
|
|
2636
|
+
manualMode ? h(
|
|
2637
|
+
"div",
|
|
2638
|
+
{ key: "manual" },
|
|
2639
|
+
h("p", { className: "dshsc-sub" }, phase === "empty" ? skippedText || t("form.noSkills") : `${t("form.probeFailed")}${error ? ` · ${error}` : ""}`),
|
|
2640
|
+
h(
|
|
2641
|
+
"label",
|
|
2642
|
+
{ className: "dshsc-field" },
|
|
2643
|
+
h("span", null, t("form.skills")),
|
|
2644
|
+
h("input", {
|
|
2645
|
+
value: manual,
|
|
2646
|
+
placeholder: "git-kit, handoff",
|
|
2647
|
+
onChange: (event) => setManual(event.target.value)
|
|
2648
|
+
})
|
|
2649
|
+
)
|
|
2650
|
+
) : null,
|
|
2651
|
+
h("p", { className: "dshsc-sub" }, t("form.hint"))
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
// client/views/modals.js
|
|
2475
2656
|
function FormModal({ t, title, hint, fields, onCancel, onSubmit }) {
|
|
2476
|
-
const [form, setForm] =
|
|
2657
|
+
const [form, setForm] = import_react4.default.useState(() => Object.fromEntries(fields.map((field) => [field.key, ""])));
|
|
2477
2658
|
const incomplete = fields.some(
|
|
2478
2659
|
(field) => field.required !== false && !String(form[field.key] || "").trim()
|
|
2479
2660
|
);
|
|
@@ -2521,14 +2702,14 @@ function LinksModal({ t, row, agents, workspaces, pickDirectory, onCancel, onSav
|
|
|
2521
2702
|
const candidates = agents.filter(
|
|
2522
2703
|
(agent) => agent.kind === "dsh" || agent.kind !== "project" && agent.exists
|
|
2523
2704
|
);
|
|
2524
|
-
const [targets, setTargets] =
|
|
2705
|
+
const [targets, setTargets] = import_react4.default.useState(() => {
|
|
2525
2706
|
const visible = new Set(candidates.map((agent) => agent.target));
|
|
2526
2707
|
const initial = new Set(row.links.map((link) => link.target).filter((target) => visible.has(target)));
|
|
2527
2708
|
initial.add("dsh-global");
|
|
2528
2709
|
return initial;
|
|
2529
2710
|
});
|
|
2530
|
-
const [scopeProjects, setScopeProjects] =
|
|
2531
|
-
const [scopeMode, setScopeMode] =
|
|
2711
|
+
const [scopeProjects, setScopeProjects] = import_react4.default.useState(row.scopeProjects || []);
|
|
2712
|
+
const [scopeMode, setScopeMode] = import_react4.default.useState((row.scopeProjects || []).length > 0 ? "projects" : "global");
|
|
2532
2713
|
const workspacePaths = new Set(workspaces.map((workspace) => workspace.path));
|
|
2533
2714
|
const otherProjects = scopeProjects.filter((project) => !workspacePaths.has(project));
|
|
2534
2715
|
const toggle = (target) => setTargets((prev) => {
|
|
@@ -2622,7 +2803,7 @@ function LinksModal({ t, row, agents, workspaces, pickDirectory, onCancel, onSav
|
|
|
2622
2803
|
);
|
|
2623
2804
|
}
|
|
2624
2805
|
function AutoLinkModal({ t, settings, agents, dsh, onCancel, onSave }) {
|
|
2625
|
-
const [targets, setTargets] =
|
|
2806
|
+
const [targets, setTargets] = import_react4.default.useState(() => new Set(
|
|
2626
2807
|
Array.isArray(settings.autoLinkTargets) ? settings.autoLinkTargets : agents.map((agent) => agent.target)
|
|
2627
2808
|
));
|
|
2628
2809
|
const toggle = (target) => setTargets((prev) => {
|
|
@@ -2678,146 +2859,6 @@ function AutoLinkModal({ t, settings, agents, dsh, onCancel, onSave }) {
|
|
|
2678
2859
|
h("p", { className: "dshsc-sub" }, t("autoLink.hint"))
|
|
2679
2860
|
);
|
|
2680
2861
|
}
|
|
2681
|
-
function AddSkillModal({ t, onCancel, onProbe, onInstall }) {
|
|
2682
|
-
const [source, setSource] = import_react3.default.useState("");
|
|
2683
|
-
const [phase, setPhase] = import_react3.default.useState("idle");
|
|
2684
|
-
const [options, setOptions] = import_react3.default.useState([]);
|
|
2685
|
-
const [selected, setSelected] = import_react3.default.useState(() => /* @__PURE__ */ new Set());
|
|
2686
|
-
const [manual, setManual] = import_react3.default.useState("");
|
|
2687
|
-
const [skipped, setSkipped] = import_react3.default.useState(0);
|
|
2688
|
-
const [error, setError] = import_react3.default.useState(null);
|
|
2689
|
-
const reset = (value) => {
|
|
2690
|
-
setSource(value);
|
|
2691
|
-
setPhase("idle");
|
|
2692
|
-
setOptions([]);
|
|
2693
|
-
setSelected(/* @__PURE__ */ new Set());
|
|
2694
|
-
setSkipped(0);
|
|
2695
|
-
setError(null);
|
|
2696
|
-
};
|
|
2697
|
-
const probe = async () => {
|
|
2698
|
-
const value = source.trim();
|
|
2699
|
-
if (!value || phase === "probing") return;
|
|
2700
|
-
setPhase("probing");
|
|
2701
|
-
setError(null);
|
|
2702
|
-
try {
|
|
2703
|
-
const result = await onProbe(value);
|
|
2704
|
-
const found = Array.isArray(result?.skills) ? result.skills : [];
|
|
2705
|
-
setOptions(found);
|
|
2706
|
-
setSelected(new Set(found.map((item) => item.name)));
|
|
2707
|
-
setSkipped(Math.max(0, Number(result?.skipped) || 0));
|
|
2708
|
-
setPhase(found.length > 0 ? "picked" : "empty");
|
|
2709
|
-
} catch (err) {
|
|
2710
|
-
setError(err?.message || String(err));
|
|
2711
|
-
setPhase("failed");
|
|
2712
|
-
}
|
|
2713
|
-
};
|
|
2714
|
-
const toggle = (name) => setSelected((prev) => {
|
|
2715
|
-
const next = new Set(prev);
|
|
2716
|
-
if (next.has(name)) next.delete(name);
|
|
2717
|
-
else next.add(name);
|
|
2718
|
-
return next;
|
|
2719
|
-
});
|
|
2720
|
-
const names = manual.split(/[,,\s]+/).map((item) => item.trim()).filter(Boolean);
|
|
2721
|
-
const skippedText = skipped > 0 ? t("form.skipped").replace("{n}", String(skipped)) : null;
|
|
2722
|
-
const manualMode = phase === "empty" || phase === "failed";
|
|
2723
|
-
const skills = phase === "picked" ? [...selected] : names;
|
|
2724
|
-
const canSubmit = phase === "picked" ? selected.size > 0 : manualMode ? names.length > 0 : false;
|
|
2725
|
-
const submit = () => {
|
|
2726
|
-
if (!canSubmit) return;
|
|
2727
|
-
onInstall({ source: source.trim(), skills });
|
|
2728
|
-
};
|
|
2729
|
-
return h(
|
|
2730
|
-
Overlay,
|
|
2731
|
-
{
|
|
2732
|
-
t,
|
|
2733
|
-
title: t("action.addSkill"),
|
|
2734
|
-
onCancel,
|
|
2735
|
-
footer: [
|
|
2736
|
-
h("button", { key: "c", className: "dshsc-btn ghost", onClick: onCancel }, t("action.cancel")),
|
|
2737
|
-
h("button", {
|
|
2738
|
-
key: "s",
|
|
2739
|
-
className: "dshsc-btn primary",
|
|
2740
|
-
disabled: !canSubmit,
|
|
2741
|
-
onClick: submit
|
|
2742
|
-
}, t("action.save"))
|
|
2743
|
-
]
|
|
2744
|
-
},
|
|
2745
|
-
h("p", { className: "dshsc-sub" }, t("form.pickHint")),
|
|
2746
|
-
h(
|
|
2747
|
-
"div",
|
|
2748
|
-
{ className: "dshsc-field" },
|
|
2749
|
-
h("span", null, t("form.source")),
|
|
2750
|
-
h(
|
|
2751
|
-
"div",
|
|
2752
|
-
{ className: "dshsc-inline" },
|
|
2753
|
-
h("input", {
|
|
2754
|
-
value: source,
|
|
2755
|
-
placeholder: t("form.sourceHint"),
|
|
2756
|
-
onChange: (event) => reset(event.target.value),
|
|
2757
|
-
onKeyDown: (event) => {
|
|
2758
|
-
if (event.key === "Enter") void probe();
|
|
2759
|
-
}
|
|
2760
|
-
}),
|
|
2761
|
-
h("button", {
|
|
2762
|
-
className: "dshsc-btn",
|
|
2763
|
-
disabled: !source.trim() || phase === "probing",
|
|
2764
|
-
onClick: () => void probe()
|
|
2765
|
-
}, phase === "probing" ? t("form.probing") : t("form.probe"))
|
|
2766
|
-
)
|
|
2767
|
-
),
|
|
2768
|
-
phase === "picked" ? h(
|
|
2769
|
-
"div",
|
|
2770
|
-
{ key: "picked" },
|
|
2771
|
-
h("div", { className: "dshsc-group" }, t("form.detected").replace("{n}", String(options.length))),
|
|
2772
|
-
h(
|
|
2773
|
-
"div",
|
|
2774
|
-
{ style: { display: "flex", gap: 6, marginBottom: 6 } },
|
|
2775
|
-
h("button", {
|
|
2776
|
-
className: "dshsc-btn ghost",
|
|
2777
|
-
onClick: () => setSelected(new Set(options.map((item) => item.name)))
|
|
2778
|
-
}, t("form.selectAll")),
|
|
2779
|
-
h("button", {
|
|
2780
|
-
className: "dshsc-btn ghost",
|
|
2781
|
-
onClick: () => setSelected(/* @__PURE__ */ new Set())
|
|
2782
|
-
}, t("form.selectNone"))
|
|
2783
|
-
),
|
|
2784
|
-
h("div", { className: "dshsc-panel" }, options.map((option) => h(
|
|
2785
|
-
"label",
|
|
2786
|
-
{ className: "dshsc-check dshsc-skill", key: option.name },
|
|
2787
|
-
h("input", {
|
|
2788
|
-
type: "checkbox",
|
|
2789
|
-
checked: selected.has(option.name),
|
|
2790
|
-
onChange: () => toggle(option.name)
|
|
2791
|
-
}),
|
|
2792
|
-
h(
|
|
2793
|
-
"span",
|
|
2794
|
-
{ className: "dshsc-skill-main" },
|
|
2795
|
-
h("span", { className: "dshsc-skill-name" }, option.name),
|
|
2796
|
-
option.description ? h("small", { className: "dshsc-skill-desc" }, option.description) : null,
|
|
2797
|
-
h("small", { className: "dshsc-skill-path" }, option.skillPath)
|
|
2798
|
-
)
|
|
2799
|
-
))),
|
|
2800
|
-
skippedText ? h("p", { className: "dshsc-sub" }, skippedText) : null
|
|
2801
|
-
) : null,
|
|
2802
|
-
phase === "probing" ? h("p", { className: "dshsc-sub" }, t("form.probingHint")) : null,
|
|
2803
|
-
manualMode ? h(
|
|
2804
|
-
"div",
|
|
2805
|
-
{ key: "manual" },
|
|
2806
|
-
h("p", { className: "dshsc-sub" }, phase === "empty" ? skippedText || t("form.noSkills") : `${t("form.probeFailed")}${error ? ` · ${error}` : ""}`),
|
|
2807
|
-
h(
|
|
2808
|
-
"label",
|
|
2809
|
-
{ className: "dshsc-field" },
|
|
2810
|
-
h("span", null, t("form.skills")),
|
|
2811
|
-
h("input", {
|
|
2812
|
-
value: manual,
|
|
2813
|
-
placeholder: "git-kit, handoff",
|
|
2814
|
-
onChange: (event) => setManual(event.target.value)
|
|
2815
|
-
})
|
|
2816
|
-
)
|
|
2817
|
-
) : null,
|
|
2818
|
-
h("p", { className: "dshsc-sub" }, t("form.hint"))
|
|
2819
|
-
);
|
|
2820
|
-
}
|
|
2821
2862
|
function Modals({ t, modal, data, autoLinkAgents, autoLinkDsh, pickDirectory, actions, onClose, onSaveAutoLink }) {
|
|
2822
2863
|
if (modal.type === "add-skill") {
|
|
2823
2864
|
return h(AddSkillModal, {
|
|
@@ -2900,7 +2941,7 @@ ${conflicts.map((item) => `${item.label}: ${item.linkPath}`).join("\n")}`,
|
|
|
2900
2941
|
}
|
|
2901
2942
|
|
|
2902
2943
|
// client/views/skill-reader.js
|
|
2903
|
-
var
|
|
2944
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
2904
2945
|
|
|
2905
2946
|
// client/markdown.js
|
|
2906
2947
|
function classifyHref(href) {
|
|
@@ -3183,7 +3224,7 @@ function resolveRelativeHref(currentDir, href) {
|
|
|
3183
3224
|
return { relPath: out.join("/"), anchor: target.kind === "anchor" ? target.href : "" };
|
|
3184
3225
|
}
|
|
3185
3226
|
|
|
3186
|
-
// client/views/
|
|
3227
|
+
// client/views/markdown-view.js
|
|
3187
3228
|
var PARSE_CACHE = /* @__PURE__ */ new Map();
|
|
3188
3229
|
function parseCached(text) {
|
|
3189
3230
|
const key = String(text ?? "");
|
|
@@ -3196,49 +3237,6 @@ function parseCached(text) {
|
|
|
3196
3237
|
}
|
|
3197
3238
|
return parsed;
|
|
3198
3239
|
}
|
|
3199
|
-
function formatBytes(bytes) {
|
|
3200
|
-
const value = Number(bytes) || 0;
|
|
3201
|
-
if (value < 1024) return `${value} B`;
|
|
3202
|
-
if (value < 1024 * 1024) return `${(value / 1024).toFixed(value < 10 * 1024 ? 1 : 0)} KB`;
|
|
3203
|
-
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
3204
|
-
}
|
|
3205
|
-
function formatWhen(iso) {
|
|
3206
|
-
if (!iso) return null;
|
|
3207
|
-
const date = new Date(iso);
|
|
3208
|
-
if (Number.isNaN(date.getTime())) return null;
|
|
3209
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
3210
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
3211
|
-
}
|
|
3212
|
-
var MARKDOWN = /\.(md|markdown)$/i;
|
|
3213
|
-
function isMarkdownPath(relPath) {
|
|
3214
|
-
return MARKDOWN.test(String(relPath || ""));
|
|
3215
|
-
}
|
|
3216
|
-
function isScroller(node) {
|
|
3217
|
-
if (!node || typeof getComputedStyle !== "function") return false;
|
|
3218
|
-
const style = getComputedStyle(node);
|
|
3219
|
-
return Boolean(style && /(auto|scroll)/.test(style.overflowY || "") && node.scrollHeight > node.clientHeight + 4);
|
|
3220
|
-
}
|
|
3221
|
-
function nearestScroller(node) {
|
|
3222
|
-
let current = node?.parentElement || null;
|
|
3223
|
-
while (current) {
|
|
3224
|
-
if (isScroller(current)) return current;
|
|
3225
|
-
current = current.parentElement || null;
|
|
3226
|
-
}
|
|
3227
|
-
return typeof document !== "undefined" ? document.scrollingElement || null : null;
|
|
3228
|
-
}
|
|
3229
|
-
function scrollHost(node) {
|
|
3230
|
-
if (isScroller(node)) return node;
|
|
3231
|
-
return node && nearestScroller(node) || node;
|
|
3232
|
-
}
|
|
3233
|
-
var STATUS_KEY = {
|
|
3234
|
-
current: "status.current",
|
|
3235
|
-
"update-available": "status.update",
|
|
3236
|
-
"locally-modified": "status.local",
|
|
3237
|
-
conflict: "status.conflict",
|
|
3238
|
-
"upstream-deleted": "status.deleted",
|
|
3239
|
-
"broken-link": "status.broken",
|
|
3240
|
-
unmanaged: "status.unmanaged"
|
|
3241
|
-
};
|
|
3242
3240
|
function inlineNodes(nodes, { onOpenFile, onOpenAnchor, keyPrefix = "i" }) {
|
|
3243
3241
|
if (!Array.isArray(nodes)) return null;
|
|
3244
3242
|
return nodes.map((node, index) => {
|
|
@@ -3371,6 +3369,34 @@ function Markdown({ text, onOpenFile, onOpenAnchor }) {
|
|
|
3371
3369
|
const { blocks } = parseCached(text);
|
|
3372
3370
|
return h("div", { className: "dshsc-md" }, blockNodes(blocks, { onOpenFile, onOpenAnchor }));
|
|
3373
3371
|
}
|
|
3372
|
+
|
|
3373
|
+
// client/views/skill-reader.js
|
|
3374
|
+
function formatBytes(bytes) {
|
|
3375
|
+
const value = Number(bytes) || 0;
|
|
3376
|
+
if (value < 1024) return `${value} B`;
|
|
3377
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(value < 10 * 1024 ? 1 : 0)} KB`;
|
|
3378
|
+
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
3379
|
+
}
|
|
3380
|
+
function formatWhen(iso) {
|
|
3381
|
+
if (!iso) return null;
|
|
3382
|
+
const date = new Date(iso);
|
|
3383
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
3384
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
3385
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
3386
|
+
}
|
|
3387
|
+
var MARKDOWN = /\.(md|markdown)$/i;
|
|
3388
|
+
function isMarkdownPath(relPath) {
|
|
3389
|
+
return MARKDOWN.test(String(relPath || ""));
|
|
3390
|
+
}
|
|
3391
|
+
var STATUS_KEY = {
|
|
3392
|
+
current: "status.current",
|
|
3393
|
+
"update-available": "status.update",
|
|
3394
|
+
"locally-modified": "status.local",
|
|
3395
|
+
conflict: "status.conflict",
|
|
3396
|
+
"upstream-deleted": "status.deleted",
|
|
3397
|
+
"broken-link": "status.broken",
|
|
3398
|
+
unmanaged: "status.unmanaged"
|
|
3399
|
+
};
|
|
3374
3400
|
function TabButton({ id, label, count, active, onSelect }) {
|
|
3375
3401
|
return h("button", {
|
|
3376
3402
|
type: "button",
|
|
@@ -3411,14 +3437,17 @@ function SkillReader({
|
|
|
3411
3437
|
onToast
|
|
3412
3438
|
}) {
|
|
3413
3439
|
const { state, file, loadFile, retry } = useSkillReader(row);
|
|
3414
|
-
const [tab, setTab] =
|
|
3415
|
-
const [format, setFormat] =
|
|
3416
|
-
const [docOverride, setDocOverride] =
|
|
3417
|
-
const [fileFormat, setFileFormat] =
|
|
3418
|
-
const [tocActive, setTocActive] =
|
|
3419
|
-
const
|
|
3420
|
-
const
|
|
3421
|
-
const
|
|
3440
|
+
const [tab, setTab] = import_react5.default.useState(initialTab);
|
|
3441
|
+
const [format, setFormat] = import_react5.default.useState("rendered");
|
|
3442
|
+
const [docOverride, setDocOverride] = import_react5.default.useState(null);
|
|
3443
|
+
const [fileFormat, setFileFormat] = import_react5.default.useState("rendered");
|
|
3444
|
+
const [tocActive, setTocActive] = import_react5.default.useState(null);
|
|
3445
|
+
const [descOpen, setDescOpen] = import_react5.default.useState(false);
|
|
3446
|
+
const [descClamped, setDescClamped] = import_react5.default.useState(false);
|
|
3447
|
+
const bodyRef = import_react5.default.useRef(null);
|
|
3448
|
+
const dialogRef = import_react5.default.useRef(null);
|
|
3449
|
+
const descRef = import_react5.default.useRef(null);
|
|
3450
|
+
const scrollRef = import_react5.default.useRef(0);
|
|
3422
3451
|
useOverlayLayer(variant === "drawer" || variant === "page", onClose);
|
|
3423
3452
|
const name = row?.name || "";
|
|
3424
3453
|
const tree = state.tree;
|
|
@@ -3427,20 +3456,49 @@ function SkillReader({
|
|
|
3427
3456
|
const bodyText = docOverride ? docOverride.content : state.body?.content || "";
|
|
3428
3457
|
const description = row?.description || state.body?.meta?.description || "";
|
|
3429
3458
|
const headings = tab === "doc" && bodyText ? parseCached(bodyText).headings : [];
|
|
3430
|
-
|
|
3459
|
+
import_react5.default.useEffect(() => {
|
|
3431
3460
|
setDocOverride(null);
|
|
3432
3461
|
scrollRef.current = 0;
|
|
3433
3462
|
}, [name]);
|
|
3434
|
-
|
|
3463
|
+
const descOwnerRef = import_react5.default.useRef(name);
|
|
3464
|
+
import_react5.default.useEffect(() => {
|
|
3465
|
+
if (descOwnerRef.current === name) return;
|
|
3466
|
+
descOwnerRef.current = name;
|
|
3467
|
+
setDescOpen(false);
|
|
3468
|
+
setDescClamped(false);
|
|
3469
|
+
}, [name]);
|
|
3470
|
+
import_react5.default.useLayoutEffect(() => {
|
|
3471
|
+
const node = descRef.current;
|
|
3472
|
+
if (!node) return void 0;
|
|
3473
|
+
const measure = () => {
|
|
3474
|
+
if (descOpen) return;
|
|
3475
|
+
const scroll = Number(node.scrollHeight) || 0;
|
|
3476
|
+
const client = Number(node.clientHeight) || 0;
|
|
3477
|
+
setDescClamped(scroll > client + 1);
|
|
3478
|
+
};
|
|
3479
|
+
measure();
|
|
3480
|
+
if (typeof window === "undefined" || !window.addEventListener) return void 0;
|
|
3481
|
+
window.addEventListener("resize", measure);
|
|
3482
|
+
let observer = null;
|
|
3483
|
+
if (typeof ResizeObserver === "function") {
|
|
3484
|
+
observer = new ResizeObserver(measure);
|
|
3485
|
+
observer.observe(node);
|
|
3486
|
+
}
|
|
3487
|
+
return () => {
|
|
3488
|
+
observer?.disconnect?.();
|
|
3489
|
+
window.removeEventListener("resize", measure);
|
|
3490
|
+
};
|
|
3491
|
+
}, [description, descOpen]);
|
|
3492
|
+
import_react5.default.useEffect(() => {
|
|
3435
3493
|
if (!initialFile) return;
|
|
3436
3494
|
setTab("files");
|
|
3437
3495
|
void loadFile(initialFile);
|
|
3438
3496
|
}, [initialFile, loadFile]);
|
|
3439
|
-
|
|
3497
|
+
import_react5.default.useEffect(() => {
|
|
3440
3498
|
const node = bodyRef.current;
|
|
3441
3499
|
if (node && scrollRef.current) node.scrollTop = scrollRef.current;
|
|
3442
3500
|
});
|
|
3443
|
-
|
|
3501
|
+
import_react5.default.useEffect(() => {
|
|
3444
3502
|
if (variant !== "drawer" || typeof document === "undefined") return void 0;
|
|
3445
3503
|
const previous = document.activeElement;
|
|
3446
3504
|
const node = dialogRef.current;
|
|
@@ -3467,12 +3525,12 @@ function SkillReader({
|
|
|
3467
3525
|
previous?.focus?.();
|
|
3468
3526
|
};
|
|
3469
3527
|
}, [variant, onClose]);
|
|
3470
|
-
|
|
3528
|
+
import_react5.default.useEffect(() => {
|
|
3471
3529
|
if (variant !== "page" || typeof document === "undefined") return;
|
|
3472
3530
|
const node = document.getElementById("dshsc-reader-name");
|
|
3473
3531
|
node?.focus?.();
|
|
3474
3532
|
}, [variant, name]);
|
|
3475
|
-
|
|
3533
|
+
import_react5.default.useEffect(() => {
|
|
3476
3534
|
if (variant !== "page" || typeof window === "undefined") return void 0;
|
|
3477
3535
|
const node = bodyRef.current;
|
|
3478
3536
|
if (!node?.querySelectorAll) return void 0;
|
|
@@ -3542,7 +3600,22 @@ function SkillReader({
|
|
|
3542
3600
|
onClick: () => onClose?.()
|
|
3543
3601
|
}, "×") : null
|
|
3544
3602
|
),
|
|
3545
|
-
description ? h(
|
|
3603
|
+
description ? h(
|
|
3604
|
+
"div",
|
|
3605
|
+
{ className: "dshsc-reader-descblock" },
|
|
3606
|
+
h("p", {
|
|
3607
|
+
className: `dshsc-reader-desc${descOpen ? " expanded" : ""}`,
|
|
3608
|
+
id: "dshsc-reader-desc",
|
|
3609
|
+
ref: descRef
|
|
3610
|
+
}, description),
|
|
3611
|
+
descClamped ? h("button", {
|
|
3612
|
+
type: "button",
|
|
3613
|
+
className: "dshsc-reader-more",
|
|
3614
|
+
"aria-expanded": String(descOpen),
|
|
3615
|
+
"aria-controls": "dshsc-reader-desc",
|
|
3616
|
+
onClick: () => setDescOpen((prev) => !prev)
|
|
3617
|
+
}, t(descOpen ? "action.collapse" : "action.expand")) : null
|
|
3618
|
+
) : null,
|
|
3546
3619
|
h(
|
|
3547
3620
|
"div",
|
|
3548
3621
|
{ className: "dshsc-reader-meta" },
|
|
@@ -3835,6 +3908,7 @@ function SkillReader({
|
|
|
3835
3908
|
}, t("action.update")) : null
|
|
3836
3909
|
);
|
|
3837
3910
|
if (variant === "page") {
|
|
3911
|
+
const tocShown = headings.length > 1;
|
|
3838
3912
|
return h(
|
|
3839
3913
|
"div",
|
|
3840
3914
|
{ className: "dshsc-reader-page" },
|
|
@@ -3860,8 +3934,8 @@ function SkillReader({
|
|
|
3860
3934
|
h("div", { className: "dshsc-reader-hero" }, header),
|
|
3861
3935
|
h(
|
|
3862
3936
|
"div",
|
|
3863
|
-
{ className:
|
|
3864
|
-
|
|
3937
|
+
{ className: `dshsc-reader-layout${tocShown ? " has-toc" : ""}` },
|
|
3938
|
+
tocShown ? h(
|
|
3865
3939
|
"nav",
|
|
3866
3940
|
{ className: "dshsc-reader-toc", "aria-label": t("viewer.toc") },
|
|
3867
3941
|
h("div", { className: "dshsc-reader-toc-title" }, t("viewer.toc")),
|
|
@@ -3895,19 +3969,19 @@ function SkillReader({
|
|
|
3895
3969
|
var UPDATABLE2 = /* @__PURE__ */ new Set(["update-available", "locally-modified", "conflict"]);
|
|
3896
3970
|
function Section({ t, page = false, pickDirectory, onPlacementChange }) {
|
|
3897
3971
|
const { data, error, busy, toast, setToast, setBusy, reload, run } = useSkillsData();
|
|
3898
|
-
const [tab, setTab] =
|
|
3899
|
-
const [view, setView] =
|
|
3900
|
-
const [modal, setModal] =
|
|
3901
|
-
const [expanded, setExpanded] =
|
|
3902
|
-
const [placementBusy, setPlacementBusy] =
|
|
3903
|
-
const [placementOverride, setPlacementOverride] =
|
|
3904
|
-
const [query, setQuery] =
|
|
3905
|
-
const [viewer, setViewer] =
|
|
3906
|
-
const rootRef =
|
|
3907
|
-
const scrollPos =
|
|
3908
|
-
const restoreScroll =
|
|
3909
|
-
const [filter, setFilter] =
|
|
3910
|
-
const [builtinOpen, setBuiltinOpen] =
|
|
3972
|
+
const [tab, setTab] = import_react6.default.useState("installed");
|
|
3973
|
+
const [view, setView] = import_react6.default.useState("flat");
|
|
3974
|
+
const [modal, setModal] = import_react6.default.useState(null);
|
|
3975
|
+
const [expanded, setExpanded] = import_react6.default.useState({});
|
|
3976
|
+
const [placementBusy, setPlacementBusy] = import_react6.default.useState(null);
|
|
3977
|
+
const [placementOverride, setPlacementOverride] = import_react6.default.useState(null);
|
|
3978
|
+
const [query, setQuery] = import_react6.default.useState("");
|
|
3979
|
+
const [viewer, setViewer] = import_react6.default.useState(null);
|
|
3980
|
+
const rootRef = import_react6.default.useRef(null);
|
|
3981
|
+
const scrollPos = import_react6.default.useRef(null);
|
|
3982
|
+
const restoreScroll = import_react6.default.useRef(null);
|
|
3983
|
+
const [filter, setFilter] = import_react6.default.useState("all");
|
|
3984
|
+
const [builtinOpen, setBuiltinOpen] = import_react6.default.useState(false);
|
|
3911
3985
|
const { settingsOpen, settingsRef, settingsPlacement, closeSettings, toggleSettings } = useSettingsPopover();
|
|
3912
3986
|
const { agentTip, agentTipPos, agentTipRef, openAgentTip, closeAgentTip } = useAgentTip();
|
|
3913
3987
|
const rows = data?.installs || [];
|
|
@@ -3928,7 +4002,7 @@ function Section({ t, page = false, pickDirectory, onPlacementChange }) {
|
|
|
3928
4002
|
const agentLabels = row.links.map((link) => link.target === "dsh-global" ? "DSH" : link.label);
|
|
3929
4003
|
return [row.name, row.source || "", ...agentLabels].join(" ").toLowerCase().includes(queryText);
|
|
3930
4004
|
});
|
|
3931
|
-
|
|
4005
|
+
import_react6.default.useEffect(() => {
|
|
3932
4006
|
if (!viewer || !data) return;
|
|
3933
4007
|
if (rows.some((row) => row.name === viewer.name)) return;
|
|
3934
4008
|
setViewer(null);
|
|
@@ -3940,23 +4014,10 @@ function Section({ t, page = false, pickDirectory, onPlacementChange }) {
|
|
|
3940
4014
|
const autoLinkDsh = (data?.agents?.all || []).find((agent) => agent.target === "dsh-global") || null;
|
|
3941
4015
|
const autoLinkLabel = [t("links.dshGlobal"), ...autoLinkAgents.map((agent) => agent.label)].join("、");
|
|
3942
4016
|
const placement = (placementOverride ?? data?.settings?.placement) === "sidebar" ? "sidebar" : "settings";
|
|
3943
|
-
function getScrollParent(node) {
|
|
3944
|
-
let current = node?.parentElement || null;
|
|
3945
|
-
while (current) {
|
|
3946
|
-
if (typeof getComputedStyle === "function") {
|
|
3947
|
-
const style = getComputedStyle(current);
|
|
3948
|
-
if (style && /(auto|scroll)/.test(style.overflowY || "") && current.scrollHeight > current.clientHeight) {
|
|
3949
|
-
return current;
|
|
3950
|
-
}
|
|
3951
|
-
}
|
|
3952
|
-
current = current.parentElement || null;
|
|
3953
|
-
}
|
|
3954
|
-
return typeof document !== "undefined" ? document.scrollingElement || null : null;
|
|
3955
|
-
}
|
|
3956
4017
|
function listScroller() {
|
|
3957
4018
|
const node = rootRef.current?.querySelector?.(".dshsc-listscroll");
|
|
3958
|
-
if (node
|
|
3959
|
-
return
|
|
4019
|
+
if (isScroller(node)) return node;
|
|
4020
|
+
return nearestScroller(rootRef.current);
|
|
3960
4021
|
}
|
|
3961
4022
|
function openViewer(row, mode = "drawer") {
|
|
3962
4023
|
if (!row) return;
|
|
@@ -3976,7 +4037,7 @@ function Section({ t, page = false, pickDirectory, onPlacementChange }) {
|
|
|
3976
4037
|
if (viewer?.mode === "page") restoreScroll.current = scrollPos.current;
|
|
3977
4038
|
setViewer(null);
|
|
3978
4039
|
}
|
|
3979
|
-
|
|
4040
|
+
import_react6.default.useLayoutEffect(() => {
|
|
3980
4041
|
if (restoreScroll.current === null) return;
|
|
3981
4042
|
const target = restoreScroll.current;
|
|
3982
4043
|
restoreScroll.current = null;
|
|
@@ -4043,7 +4104,7 @@ function Section({ t, page = false, pickDirectory, onPlacementChange }) {
|
|
|
4043
4104
|
onToast: (next) => setToast(next)
|
|
4044
4105
|
}) : null;
|
|
4045
4106
|
const listNode = h(
|
|
4046
|
-
|
|
4107
|
+
import_react6.default.Fragment,
|
|
4047
4108
|
null,
|
|
4048
4109
|
h(Header, {
|
|
4049
4110
|
t,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morehao/dsh-skills-console",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "统一管理本地技能的安装、更新、删除与接入,让同一份技能在多个 Agent 间复用。A skill manager for DeepSeek Harness: install, update, remove, link and toggle agent skills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "morehao <morehao@qq.com>",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
"build:client": "node scripts/build-client.mjs",
|
|
53
53
|
"dev:client": "node scripts/build-client.mjs --watch",
|
|
54
54
|
"check:client": "node scripts/build-client.mjs --check",
|
|
55
|
-
"check": "node scripts/check-
|
|
55
|
+
"check:cycles": "node scripts/check-cycles.mjs",
|
|
56
|
+
"check": "node scripts/check-syntax.mjs && node scripts/check-cycles.mjs && node scripts/build-client.mjs --check && node scripts/check-naming.mjs && node scripts/check-pack.mjs && node scripts/smoke-release-notes.mjs",
|
|
56
57
|
"check:syntax": "node scripts/check-syntax.mjs",
|
|
57
58
|
"check:naming": "node scripts/check-naming.mjs",
|
|
58
59
|
"check:pack": "node scripts/check-pack.mjs",
|