dsh-m 0.9.69 → 0.9.71

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/CHANGELOG.md CHANGED
@@ -8,6 +8,20 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
8
8
 
9
9
  ## 中文
10
10
 
11
+ ### 0.9.71 功能:设置类操作记录——社区目录开关与清单源变更入账(DESIGN §2.6 修订)
12
+
13
+ - **背景**:设置页「社区目录开关」与「校验并应用 / 恢复默认」(清单源)的变更此前不入操作记录,事后无法回看「何时改的、从哪改到哪」——而 agent 供给面(`dshm_search` 可见目录规模 20 余精选 ↔ 4,000+ 社区)与信任根(自定义清单源)恰恰挂在这两个开关上。
14
+ - **方案(DESIGN §2.6 修订)**:操作记录边界从包级事务扩至**供给面/信任边界设置变更**,新增两类**终态直落**记录(不入泵、创建即终态、不参与恢复重放;恢复原样保留 / 清除 / 红点语义天然兼容):`community-toggle` 成败皆记(失败 = 已接受的变更尝试中途回滚,有「以为关了其实没关」的误信风险;meta.on),`registry-url` 仅记成功(校验拒绝零状态变更且卡片红字就地呈现,高频试错入记录只会制造红点噪音;target = 新地址、恢复默认记 `(default)`,meta.from = 原地址)。记录行 target 展示派生:开关按 meta.on 显「开/关」,清单源保持 URL。
15
+ - **口径**:面板发起的变更(CLI、`dsh plugin add`、DSH 设置表单直改不留痕,与包操作既有口径一致)。
16
+ - **评审**:独立 subagent 盲评 0 blocker / 0 major,4 minor + 3 nit 全部随本版修掉(done 打点紧贴 api 成功消除刷新链吞错隐式依赖;测试计数桩钉死「终态不咨询恢复谓词」;`(default)` 收敛共享常量等)。
17
+ - **验证**:1326 项测试全绿(新增设置类终态直落 describe 块 3 用例)、typecheck 零错误。
18
+
19
+ ### 0.9.70 修复:拖拽观感与静止态一致——退役拖拽期实心固化(ADR-0017 v2)
20
+
21
+ - **根因(用户浅色模式双态实拍)**:0.9.69 的拖拽期「计算值固化强制实心」在按住/松手瞬间造成实心↔玻璃的观感跳变,浅色模式下尤为突兀——防透字与观感连续两个目标里,实心方案牺牲了后者。
22
+ - **修复(ADR-0017 决策 3 修订 v2)**:拖拽态与静止态**同玻璃同 blur,外观逐像素一致**——透字防护回归静止态既有不变量(毛玻璃模糊背景自持;透字病灶的成因是「关 blur 还留半透明」,两样都不动即无此病,openbmc 静止态可读性本就由 blur 兜住)。拖拽可供性只剩 grabbing 光标与投影加深;`solidifyColor`/`--dshm-drag-bg`/拖拽态 `!important` 全部退役(清单定长回归 4,`client-lightbox` 断言含「无残留」负向锚)。性能保底手段(pointer capture/手势期监听/rAF 帧内写/translate3d/will-change)全部保留;拖拽期恢复的每帧 backdrop 重滤镜由 GPU 合成承担,弱机若报告掉帧再评估。
23
+ - **验证**:1323 项测试全绿、typecheck 零错误;ADR-0017 修订 v2(Considered Options 翻案记录在案)。
24
+
11
25
  ### 0.9.69 功能:还原态面板头部拖拽 + 位置记忆(ADR-0017)
12
26
 
13
27
  - **方案**:市场面板(`.dshm-panel`)还原态下按住头部(标题/tab 行)即可自由拖拽——头部全域为手柄,tab/全屏/关闭钮点击语义原样(`closest("button")` 门卫 + 多指重入守卫);双击头部非按钮区切换全屏;释放位置烘焙为视口绝对坐标存 `dshm-panel-pos`,下次打开还原,无记忆首开与旧版 flex 居中渲染逐字节一致。运动范围四周 8px;desktop profile 额外让出壳层标题拖拽带(quota-watch 契约:`data-windows-titlebar` + `--dsh-windows-titlebar-height`,web 无此变量恒 0)——胶囊时代「停进系统按钮区就再也抓不回」的坑由 clamp 机制性杜绝。挂载/全屏往返/resize 三触发源重夹紧,还原 commit 的重夹紧时序由 render 期 latest-ref 镜像保证(执行评审 E1-1 实证修复并以结构锚钉死)。
@@ -511,6 +525,20 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
511
525
 
512
526
  ## English
513
527
 
528
+ ### Feature in 0.9.71 — settings-class operation records: community catalog toggle and registry source changes are now logged (DESIGN §2.6 revision)
529
+
530
+ - **Background**: changes made via the settings page's community catalog toggle and the registry source actions (apply / restore default) never appeared in the operations panel, leaving no answer to "when was it changed, and from what" — even though the agent-facing supply surface (`dshm_search` scope: ~20 curated vs 4,000+ community entries) and the trust root (custom registry source) hang exactly on these two switches.
531
+ - **Design (DESIGN §2.6 revision)**: the operations-log boundary expands from package-level transactions to **supply-scope / trust-boundary settings changes**, adding two **terminal-at-creation** record kinds (never enqueued, no queued lifecycle, no restore replay; restore-passthrough / clear / red-dot semantics work unchanged): `community-toggle` records both success and failure (failure = an accepted mutation attempt rolled back mid-flight — the "thought it was off but it wasn't" risk; meta.on), `registry-url` records success only (validation rejections change nothing and surface inline in the card; logging every typo would only manufacture red-dot noise; target = new address, restore default logged as `(default)`, meta.from = previous address). Row display derivation: the toggle shows On/Off from meta.on; the registry source keeps the URL.
532
+ - **Scope**: panel-initiated changes only (CLI, `dsh plugin add`, and DSH settings-form direct writes leave no record — consistent with the existing package-operations scope).
533
+ - **Review**: independent subagent blind review found 0 blockers / 0 majors; all 4 minors + 3 nits fixed in this release (done-record placement now hugs api success, removing an implicit reliance on the refresh chain's error swallowing; a counting stub pins "terminal records never consult the restore predicate"; `(default)` converged into a shared constant).
534
+ - **Verification**: 1326 tests green (new terminal-at-creation describe block with 3 cases), typecheck clean.
535
+
536
+ ### Fix in 0.9.70 — drag appearance matches the resting state: drag-time solidification retired (ADR-0017 v2)
537
+
538
+ - **Root cause (user side-by-side capture in light mode)**: the 0.9.69 drag-time "computed-value solidification" made the panel jump between solid and glass at grab/release - jarring in light mode. Of the two goals (no see-through, visual continuity), the solid approach sacrificed continuity.
539
+ - **Fix (ADR-0017 decision 3 revised to v2)**: the drag state now shares the resting state's exact glass and blur - pixel-identical appearance. See-through protection returns to the resting invariant (frosted blur holds the background; the disease class was "blur off while still translucent" - leave both untouched and it cannot occur, exactly how openbmc's resting readability is already held). Drag affordance reduces to the grabbing cursor and a deeper shadow; `solidifyColor` / `--dshm-drag-bg` / drag-time `!important` are all retired (inventory back to a pinned 4, with a no-residue negative anchor in `client-lightbox`). The performance toolbox (pointer capture / gesture-scoped listeners / rAF-frame writes / translate3d / will-change) is fully retained; the restored per-frame backdrop re-filter is carried by GPU compositing - revisit only if weak-GPU jank is reported.
540
+ - **Verification**: 1323 tests green, typecheck clean; ADR-0017 revised to v2 (Considered Options overruling recorded).
541
+
514
542
  ### Feature in 0.9.69 — drag the marketplace panel by its header in restore state, with position memory (ADR-0017)
515
543
 
516
544
  - **Design**: hold the panel header (title/tab row) in restore state to drag the marketplace panel freely - the whole header is the handle while tab / fullscreen / close buttons keep their click semantics (`closest("button")` gate + multi-pointer re-entry guard); double-click on a non-button header area toggles fullscreen; on release the position is baked into absolute viewport coordinates and stored under `dshm-panel-pos`, restored on next open - with no stored position the first render stays byte-identical to the old flex-centered layout. The motion range is clamped 8px on all sides; the desktop profile additionally yields the shell titlebar drag band (quota-watch contract: `data-windows-titlebar` + `--dsh-windows-titlebar-height`; web without the variable is always 0) - the capsule-era trap of parking inside the system button zone and never being grabbable again is eliminated by construction. Mount, fullscreen round-trips and window resize all re-clamp; the restore-commit re-clamp is ordered by render-phase latest-ref mirrors (execution review E1-1, reproduced, fixed, and pinned by structural anchors).
package/docs/DESIGN.md CHANGED
@@ -94,6 +94,7 @@
94
94
  - **详情 = Modal 且为卡片超集**(「detail 显示少于摘要就是倒退」):byline / 分类 / 收录日期 / 下载量窗口三要素(计数 + 窗口 + 核对时间)/ 描述全文 / 截图灯箱(←→/Esc、**禁自动轮播**)/ 能力披露 + 红线(**默认收起**)/ 安装命令折叠行(0.9.14 起按上下文显隐:desktop 上下文与已安装条目整行隐藏——命令两来源恒为 `--profile web` 语义,desktop 装机走弹窗内安装按钮)/ deprecated 替代链接;精选条目超集另加 verified 与 tags。**安装确认走 Modal**。安装信息就地显示(0.9.15):进行中进度行与终态结果行挂 Modal 内、底层同源进度行让位——展示派生自全局操作记录,§2.6「状态不挂卡片」所有权模型不变。卡片瘦身:能力披露、截图、安装命令全部迁出卡片(Q44 精神「只在详情层、默认收起」不变,载体升级)。
95
95
  - **详情截图来源(2026-10-09,[ADR-0015](./adr/0015-primary-screenshot-manifest.md))**:Community live 条目沿用 `CommunityEntry.screenshots`(来自版本化 `dsh-plugin-catalog`);Primary DetailModal 调 GUI Host method `primary-screenshots({ id })`,Host 按 active Primary Registry 精确查 id 与 `github`,仅当 `github` 存在时懒读仓库根 `screenshots.json`(HEAD)。清单为顶层最多 8 个仓库相对路径;缺 github、缺文件、无效内容或网络失败均返回空列表,不回退 Community Catalog、README 或 npm repository。清单只在 Modal state/Host 内存缓存(成功结果 10 分钟、空/失败结果负缓存 1 分钟),不进入 `MarketItem`、市场 localStorage 快照、收藏快照、Agent 工具或 CLI;最终图片仍经现有 `safeScreenshots` 与 [ADR-0014](./adr/0014-image-chain-weserv-first.md) 的 `useImgChain`。`source='primary'` 是 market 分区参数,与 `primary-screenshots` Host method 分离;现有 Community Zone 可独立加载社区数据。
96
96
  - **全局操作记录**:每个变更操作一条 record(`queued / running / input=冲突待决 / done / warned / failed`),**状态不挂卡片**——翻页、搜索、切 tab 不丢;**localStorage 持久化队列**,宿主重载恢复时逐条校验「此刻仍成立才执行,否则报告」;覆盖安装、升级、卸载、开关。已装侧跟随一致化:「全部更新 (N)」批量入口 + tab 更新红点 + 卡片视觉与发现侧同体系;组管理、个人备注列 backlog。
97
+ - **修订(2026-10-10):设置类终态直落记录**——边界从包级事务扩至**供给面/信任边界设置变更**,新增两类**不入泵**的记录(创建即终态,无 queued 生命周期、无恢复重放;恢复分支原样保留、清除/红点语义照常):`community-toggle`(社区目录开关,**成败皆记**——失败 = 已接受的变更尝试中途回滚,有「以为关了其实没关」的误信风险,红点值得点亮;meta.on)与 `registry-url`(清单源变更 = 信任根变更,**仅记成功**——校验拒绝无任何状态变更且卡片红字就地呈现,高频试错入记录只会制造红点噪音;target = 新地址、恢复默认记 `"(default)"`,meta.from = 原地址;记录行的 target 展示派生:community-toggle 按 meta.on 显「开/关」,registry-url 保持 URL 原样)。选型依据:低频 × 高影响 × 事后回看是操作记录的靶面,瞬时原子配置写没有可跟踪的后台过程,入泵属语义错配。**口径 = 面板发起**的变更:CLI、`dsh plugin add`、DSH 设置表单(settings-compat forms store)与配置文件直改不留痕,与包操作口径一致。
97
98
  - **收藏**:浏览器 localStorage 本地收藏(不进 profile、不进服务端);收藏区 stale 条目(目录中已下架)单独提示 + 一键清理。
98
99
  - **agent/CLI 契约(允许破坏性变更)**:`dshm_search` 参数改为 `query / category / source('primary'|'community'|'all',默认 all,与 GUI 分区对齐) / limit(默认 10,clamp 1–80) / offset(真翻页)`;`primary_only` 删除。输出补 `community` 标记与 `downloads/stars`;社区分类直出中文标签(不再回退英文 slug);工具描述整体重写(真实规模 + 翻页语义,删「registry is curated & small」)。CLI 对齐 `--source / --offset / --limit`,默认 10 条。
99
100
  - **技术默认件**:图片三层懒加载(IntersectionObserver + `loading=lazy` + `fetchPriority=low`;缩略图本机直连原图,不引第三方代理服务);移除客户端重复排序(服务端单一排序源);`total>200` 性能提示随分区退役;host-api limit 上限对齐新页大小;空状态逐分区定制;错误态带具体原因 + 重试。
package/lib/client.js CHANGED
@@ -507,7 +507,6 @@ __export(window_drag_exports, {
507
507
  isDragTarget: () => isDragTarget,
508
508
  loadPanelPos: () => loadPanelPos,
509
509
  savePanelPos: () => savePanelPos,
510
- solidifyColor: () => solidifyColor,
511
510
  titlebarTopInset: () => titlebarTopInset
512
511
  });
513
512
  function dragSlop(pointerType) {
@@ -545,29 +544,6 @@ function clampPoint(point, viewport, size = 0, insets = ZERO_INSETS) {
545
544
  y: Math.min(Math.max(point.y, minY), maxY)
546
545
  };
547
546
  }
548
- function solidifyColor(computedColor) {
549
- if (typeof computedColor !== "string") return null;
550
- const srgb = COLOR_SRGB_RE.exec(computedColor.trim());
551
- if (srgb) {
552
- const alpha = srgb[4] !== void 0 ? Number.parseFloat(srgb[4]) : 1;
553
- if (!Number.isFinite(alpha) || alpha < 0.05) return null;
554
- const to255 = (v) => Math.round(Number.parseFloat(v) * 255);
555
- return `rgb(${to255(srgb[1])}, ${to255(srgb[2])}, ${to255(srgb[3])})`;
556
- }
557
- const rgb = RGB_RE.exec(computedColor.trim());
558
- if (rgb) {
559
- const parts = rgb[1].split(",").map((p) => p.trim());
560
- if (parts.length !== 3 && parts.length !== 4) return null;
561
- const r = Number.parseFloat(parts[0]);
562
- const g = Number.parseFloat(parts[1]);
563
- const b = Number.parseFloat(parts[2]);
564
- const a = parts.length === 4 ? Number.parseFloat(parts[3]) : 1;
565
- if (![r, g, b, a].every(Number.isFinite)) return null;
566
- if (a < 0.05) return null;
567
- return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
568
- }
569
- return null;
570
- }
571
547
  function loadPanelPos(storage) {
572
548
  if (!storage || typeof storage.getItem !== "function") return null;
573
549
  try {
@@ -594,7 +570,7 @@ function savePanelPos(storage, point) {
594
570
  function isDragTarget(el) {
595
571
  return Boolean(el?.closest?.("button"));
596
572
  }
597
- var POS_KEY, PANEL_MARGIN, DRAG_SLOP_MOUSE, DRAG_SLOP_TOUCH, ZERO_INSETS, RGB_RE, COLOR_SRGB_RE;
573
+ var POS_KEY, PANEL_MARGIN, DRAG_SLOP_MOUSE, DRAG_SLOP_TOUCH, ZERO_INSETS;
598
574
  var init_window_drag = __esm({
599
575
  "src/client/window-drag.js"() {
600
576
  "use strict";
@@ -603,8 +579,6 @@ var init_window_drag = __esm({
603
579
  DRAG_SLOP_MOUSE = 6;
604
580
  DRAG_SLOP_TOUCH = 10;
605
581
  ZERO_INSETS = { left: 0, right: 0, top: 0, bottom: 0 };
606
- RGB_RE = /^rgba?\(([^)]+)\)$/i;
607
- COLOR_SRGB_RE = /^color\(srgb\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)(?:\s*\/\s*([0-9.]+))?\)$/i;
608
582
  }
609
583
  });
610
584
 
@@ -1323,6 +1297,7 @@ var init_installed_updates = __esm({
1323
1297
  var operations_exports = {};
1324
1298
  __export(operations_exports, {
1325
1299
  OP_STORAGE_KEY: () => OP_STORAGE_KEY,
1300
+ REGISTRY_DEFAULT_TARGET: () => REGISTRY_DEFAULT_TARGET,
1326
1301
  TERMINAL_CLEARABLE: () => TERMINAL_CLEARABLE,
1327
1302
  createOperationsStore: () => createOperationsStore,
1328
1303
  createOpsPump: () => createOpsPump,
@@ -1579,11 +1554,12 @@ async function drainRestored(store, dispatch, stillApplies) {
1579
1554
  }
1580
1555
  }
1581
1556
  }
1582
- var OP_STORAGE_KEY, TERMINAL_CLEARABLE;
1557
+ var OP_STORAGE_KEY, REGISTRY_DEFAULT_TARGET, TERMINAL_CLEARABLE;
1583
1558
  var init_operations = __esm({
1584
1559
  "src/client/operations.js"() {
1585
1560
  "use strict";
1586
1561
  OP_STORAGE_KEY = "dshm-operations";
1562
+ REGISTRY_DEFAULT_TARGET = "(default)";
1587
1563
  TERMINAL_CLEARABLE = /* @__PURE__ */ new Set(["done", "warned", "failed", "superseded"]);
1588
1564
  }
1589
1565
  });
@@ -1782,7 +1758,7 @@ var { DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE2, MARKET_PAGE_SIZES: MARKET_PAGE_SIZE
1782
1758
  var { readMarketSnapshot: readMarketSnapshot2, writeMarketSnapshot: writeMarketSnapshot2, isDefaultFirstPageQuery: isDefaultFirstPageQuery2 } = (init_market_snapshot(), __toCommonJS(market_snapshot_exports));
1783
1759
  var { backdropCloseHandlers: backdropCloseHandlers2 } = (init_backdrop(), __toCommonJS(backdrop_exports));
1784
1760
  var { lbStep: lbStep2, lbNeighbors: lbNeighbors2, swipeDir: swipeDir2 } = (init_lightbox(), __toCommonJS(lightbox_exports));
1785
- var { dragSlop: dragSlop2, grabOffset: grabOffset2, titlebarTopInset: titlebarTopInset2, clampPoint: clampPoint2, solidifyColor: solidifyColor2, loadPanelPos: loadPanelPos2, savePanelPos: savePanelPos2, isDragTarget: isDragTarget2 } = (init_window_drag(), __toCommonJS(window_drag_exports));
1761
+ var { dragSlop: dragSlop2, grabOffset: grabOffset2, titlebarTopInset: titlebarTopInset2, clampPoint: clampPoint2, loadPanelPos: loadPanelPos2, savePanelPos: savePanelPos2, isDragTarget: isDragTarget2 } = (init_window_drag(), __toCommonJS(window_drag_exports));
1786
1762
  var { WESERV_TIMEOUT_MS: WESERV_TIMEOUT_MS2, weservUrl: weservUrl2, serviceBucketOf: serviceBucketOf2, tierOrder: tierOrder2, nextTier: nextTier2, needsTimeout: needsTimeout2, preferredTier: preferredTier2, rememberSuccess: rememberSuccess2 } = (init_img_chain(), __toCommonJS(img_chain_exports));
1787
1763
  var { createMarkdown: createMarkdown2 } = (init_markdown(), __toCommonJS(markdown_exports));
1788
1764
  var { ExtLink, MdImg, renderMarkdown } = createMarkdown2(h);
@@ -1792,7 +1768,7 @@ var { pickPayload: pickPayload2, parseToolArgs: parseToolArgs2 } = (init_tool_vi
1792
1768
  var { RESTART_POLL_MS: RESTART_POLL_MS2, RESTART_DEADLINE_MS: RESTART_DEADLINE_MS2, nextRestartWait: nextRestartWait2, isAmbiguousRestartRequestError: isAmbiguousRestartRequestError2 } = (init_restart_wait(), __toCommonJS(restart_wait_exports));
1793
1769
  var { refreshAfterMutation: refreshAfterMutation2 } = (init_view_refresh(), __toCommonJS(view_refresh_exports));
1794
1770
  var { applyInstalledUpdates: applyInstalledUpdates2, installedUpdateStats: installedUpdateStats2 } = (init_installed_updates(), __toCommonJS(installed_updates_exports));
1795
- var { createOperationsStore: createOperationsStore2, restoreRecords: restoreRecords2, createOpsPump: createOpsPump2, opAppliesTo: opAppliesTo2, TERMINAL_CLEARABLE: TERMINAL_CLEARABLE2, upgradeNotify: upgradeNotify2 } = (init_operations(), __toCommonJS(operations_exports));
1771
+ var { createOperationsStore: createOperationsStore2, restoreRecords: restoreRecords2, createOpsPump: createOpsPump2, opAppliesTo: opAppliesTo2, TERMINAL_CLEARABLE: TERMINAL_CLEARABLE2, upgradeNotify: upgradeNotify2, REGISTRY_DEFAULT_TARGET: REGISTRY_DEFAULT_TARGET2 } = (init_operations(), __toCommonJS(operations_exports));
1796
1772
  var { createFavoritesStore: createFavoritesStore2, partitionStale: partitionStale2 } = (init_favorites(), __toCommonJS(favorites_exports));
1797
1773
  var { readSelfCheckCache: readSelfCheckCache2, writeSelfCheckCache: writeSelfCheckCache2, clearSelfCheckCache: clearSelfCheckCache2, deriveChipState: deriveChipState2 } = (init_self_check(), __toCommonJS(self_check_exports));
1798
1774
  var { shouldShowInstallCmd: shouldShowInstallCmd2 } = (init_install_cmd(), __toCommonJS(install_cmd_exports));
@@ -1841,6 +1817,10 @@ var ZH = {
1841
1817
  "op.kind.upgrade": "\u5347\u7EA7",
1842
1818
  "op.kind.uninstall": "\u5378\u8F7D",
1843
1819
  "op.kind.toggle": "\u5F00\u5173",
1820
+ "op.kind.community-toggle": "\u793E\u533A\u76EE\u5F55\u5F00\u5173",
1821
+ "op.kind.registry-url": "\u6E05\u5355\u6E90\u53D8\u66F4",
1822
+ "op.state.on": "\u5F00",
1823
+ "op.state.off": "\u5173",
1844
1824
  "op.status.queued": "\u6392\u961F\u4E2D",
1845
1825
  "op.status.running": "\u8FDB\u884C\u4E2D",
1846
1826
  "op.status.input": "\u5F85\u51B3",
@@ -2010,7 +1990,7 @@ var ZH = {
2010
1990
  "settings.community.displaced": "\u4E0E\u7CBE\u9009\u91CD\u590D",
2011
1991
  "settings.community.displaced.v": "{n} \u6761",
2012
1992
  "settings.ops": "\u64CD\u4F5C\u8BB0\u5F55",
2013
- "settings.ops.empty": "\u6682\u65E0\u64CD\u4F5C\u8BB0\u5F55\u3002\u5B89\u88C5\u3001\u5347\u7EA7\u3001\u5378\u8F7D\u4E0E\u5F00\u5173\u64CD\u4F5C\u7684\u6267\u884C\u5386\u53F2\u5C06\u5728\u8FD9\u91CC\u663E\u793A\u3002",
1993
+ "settings.ops.empty": "\u6682\u65E0\u64CD\u4F5C\u8BB0\u5F55\u3002\u5B89\u88C5\u3001\u5347\u7EA7\u3001\u5378\u8F7D\u3001\u5F00\u5173\u4E0E\u4F9B\u7ED9\u9762\u8BBE\u7F6E\uFF08\u6E05\u5355\u6E90\u3001\u793E\u533A\u76EE\u5F55\uFF09\u7684\u6267\u884C\u5386\u53F2\u5C06\u5728\u8FD9\u91CC\u663E\u793A\u3002",
2014
1994
  "settings.ops.group.active": "\u8FDB\u884C\u4E2D",
2015
1995
  "settings.ops.group.done": "\u5DF2\u7ED3\u675F",
2016
1996
  "settings.ops.reddot": "\u5B58\u5728\u5931\u8D25\u6216\u5E26\u8B66\u544A\u7684\u64CD\u4F5C\u8BB0\u5F55",
@@ -2128,6 +2108,10 @@ var EN = {
2128
2108
  "op.kind.upgrade": "Upgrade",
2129
2109
  "op.kind.uninstall": "Uninstall",
2130
2110
  "op.kind.toggle": "Toggle",
2111
+ "op.kind.community-toggle": "Community catalog toggle",
2112
+ "op.kind.registry-url": "Registry source change",
2113
+ "op.state.on": "On",
2114
+ "op.state.off": "Off",
2131
2115
  "op.status.queued": "Queued",
2132
2116
  "op.status.running": "Running",
2133
2117
  "op.status.input": "Pending",
@@ -2297,7 +2281,7 @@ var EN = {
2297
2281
  "settings.community.displaced": "Displaced (duplicates)",
2298
2282
  "settings.community.displaced.v": "{n}",
2299
2283
  "settings.ops": "Operations",
2300
- "settings.ops.empty": "No operations yet. Install, upgrade, uninstall and toggle history will appear here.",
2284
+ "settings.ops.empty": "No operations yet. History of installs, upgrades, uninstalls, toggles and registry / community catalog settings will appear here.",
2301
2285
  "settings.ops.group.active": "Active",
2302
2286
  "settings.ops.group.done": "Finished",
2303
2287
  "settings.ops.reddot": "Failed or warned operations exist",
@@ -2392,16 +2376,16 @@ function communityLabels(data) {
2392
2376
  var CSS = `
2393
2377
  .dshm-overlay{position:fixed;inset:0;z-index:2147483000;background:var(--dsw-alias-bg-mask-3,rgba(15,23,42,.48));display:flex;align-items:center;justify-content:center;padding:max(24px,var(--dsh-windows-titlebar-height,0px)) 16px 24px;box-sizing:border-box}
2394
2378
  .dshm-panel{width:min(920px,100%);height:min(680px,86vh);display:flex;flex-direction:column;background:var(--dsw-alias-bg-elevated,var(--dsw-alias-bg-base,#fff));background:color-mix(in srgb,var(--dsw-alias-bg-base,#fff) 86%,transparent);backdrop-filter:blur(14px) saturate(1.3);-webkit-backdrop-filter:blur(14px) saturate(1.3);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:14px;box-shadow:0 18px 48px rgba(2,6,23,.25);overflow:hidden;font-family:inherit;color:var(--dsw-alias-label-primary,inherit)}
2395
- /* 0.9.69 \u8FD8\u539F\u6001\u62D6\u62FD\uFF1A.abs = \u6709\u4F4D\u7F6E\u8BB0\u5FC6\u65F6\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u5F62\u6001\uFF08overlay \u4E3A inset:0 fixed\uFF0C
2379
+ /* 0.9.70 \u8FD8\u539F\u6001\u62D6\u62FD\uFF1A.abs = \u6709\u4F4D\u7F6E\u8BB0\u5FC6\u65F6\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u5F62\u6001\uFF08overlay \u4E3A inset:0 fixed\uFF0C
2396
2380
  \u7EDD\u5BF9\u5B9A\u4F4D\u5750\u6807\u5373\u89C6\u53E3\u5750\u6807\uFF09\uFF1B\u65E0\u8BB0\u5F55\u65F6\u9762\u677F\u4ECD\u8D70 overlay flex \u5C45\u4E2D\uFF0C\u6E32\u67D3\u8DEF\u5F84\u4E0E\u65E7\u7248\u9010\u5B57\u8282\u4E00\u81F4\u3002
2397
- \u62D6\u62FD\u6001\u81EA\u6301\uFF080.9.62 \u5F71\u9662\u540C\u6B3E\u7EAA\u5F8B\uFF09\uFF1Abackground \u53D6\u8C03\u7528\u65B9\u624B\u52BF\u5F00\u59CB\u65F6\u5199\u5165\u7684 --dshm-drag-bg
2398
- \uFF08getComputedStyle \u89E3\u6790\u540E\u7684\u6700\u7EC8\u8272\u5F3A\u5236 \u03B1=1\uFF0C\u89C1 window-drag.solidifyColor\uFF09\uFF0C\u76AE\u80A4\u5BF9
2399
- --dsw-alias-* \u7684\u534A\u900F\u660E\u5B9A\u4E49\uFF08openbmc/uefi bg-base \u03B1=0.55 \u75C5\u7C7B\uFF09\u65E0\u6CD5\u518D\u8BA9\u62D6\u62FD\u4E2D\u9762\u677F\u900F\u5149\uFF1B
2400
- blur \u5173\u95ED\u662F\u62D6\u62FD\u671F\u6700\u5927\u6027\u80FD\u6536\u76CA\uFF08\u6BCF\u5E27\u514D\u5927\u9762\u79EF\u91CD\u6EE4\u955C\uFF09\uFF0Ctransform \u2260 none \u7EF4\u6301\u5305\u542B\u5757\uFF0C
2401
- fixed \u540E\u4EE3\u4E0D\u9003\u9038\u3002\u81EA\u6301\u4E09\u5904\u5DF2\u767B\u8BB0\u4E8E client-lightbox.test.mjs \u5B9A\u957F\u65AD\u8A00\uFF084\u21927\uFF09\uFF1B
2402
- \u672C\u6CE8\u91CA\u523B\u610F\u4E0D\u7528\u6E05\u5355\u5173\u952E\u5B57\u5B57\u9762\u91CF\u2014\u2014\u8BA1\u6570\u5BF9\u6CE8\u91CA\u63D0\u53CA\u540C\u6837\u751F\u6548\uFF08\u8BC4\u5BA1 R1-2\uFF09\u3002 */
2381
+ \u62D6\u62FD\u89C2\u611F\u4E0D\u53D8\u91CF\uFF080.9.70 \u4FEE\u8BA2\uFF0CADR-0017 v2\uFF09\uFF1A\u62D6\u62FD\u6001\u4E0E\u9759\u6B62\u6001\u540C\u73BB\u7483\u540C blur\uFF0C\u5916\u89C2\u9010\u50CF\u7D20\u4E00\u81F4
2382
+ \u2014\u2014\u7528\u6237\u53CC\u6001\u5B9E\u62CD\u88C1\u51B3\uFF1A0.9.69 \u7684\u62D6\u62FD\u671F\u5B9E\u5FC3\u56FA\u5316\u5728\u6D45\u8272\u6A21\u5F0F\u4E0B\u5B9E/\u73BB\u7483\u8DF3\u53D8\u89C2\u611F\u7A81\u5140\uFF0C\u9000\u5F79\uFF1B
2383
+ \u900F\u5B57\u9632\u62A4\u56DE\u5F52\u9759\u6B62\u6001\u65E2\u6709\u4E0D\u53D8\u91CF\uFF08\u6BDB\u73BB\u7483\u6A21\u7CCA\u80CC\u666F\u81EA\u6301\u2014\u2014\u900F\u5B57\u75C5\u7076\u7684\u6210\u56E0\u662F\u300C\u5173 blur \u8FD8\u7559
2384
+ \u534A\u900F\u660E\u300D\uFF0C\u4E24\u6837\u90FD\u4E0D\u52A8\u5373\u65E0\u6B64\u75C5\uFF09\u3002\u62D6\u62FD\u53EF\u4F9B\u6027\u53EA\u5269 grabbing \u5149\u6807\u4E0E\u6295\u5F71\u52A0\u6DF1\uFF1B\u4EE3\u4EF7\u662F\u62D6\u62FD\u671F
2385
+ \u6062\u590D\u6BCF\u5E27 backdrop \u91CD\u6EE4\u955C\uFF08GPU \u5408\u6210\u627F\u62C5\uFF0C\u5F31\u673A\u82E5\u62A5\u544A\u6389\u5E27\u518D\u8BC4\u4F30\uFF09\uFF0C\u5E27\u5185\u5199/capture/
2386
+ \u624B\u52BF\u671F\u76D1\u542C\u7B49\u5176\u4F59\u6027\u80FD\u624B\u6BB5\u5168\u90E8\u4FDD\u7559\u3002 */
2403
2387
  .dshm-panel.abs{position:absolute;margin:0}
2404
- .dshm-panel--dragging{cursor:grabbing;background:var(--dshm-drag-bg,Canvas)!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important;box-shadow:0 24px 64px rgba(2,6,23,.38)}
2388
+ .dshm-panel--dragging{cursor:grabbing;box-shadow:0 24px 64px rgba(2,6,23,.38)}
2405
2389
  /* 0.9.69 \u62D6\u62FD\u624B\u67C4\uFF1Auser-select/touch-action/tap-highlight \u65E0\u6761\u4EF6\u751F\u6548\uFF08\u5168\u5C4F\u53CC\u51FB\u5207\u6362\u65F6
2406
2390
  \u6807\u9898\u4E0D\u51FA\u73B0\u9009\u4E2D\u95EA\u73B0\uFF09\uFF1Bgrab \u5149\u6807\u4EC5\u5728\u300C\u8FD8\u539F\u6001\u4E14\u975E\u62D6\u62FD\u4E2D\u300D\u76F4\u63A5\u547D\u4E2D head\u2014\u2014\u62D6\u62FD\u4E2D head
2407
2391
  \u65E0\u81EA\u6709 cursor \u58F0\u660E\uFF0C\u81EA\u7136\u7EE7\u627F\u9762\u677F\u6839 .dshm-panel--dragging \u7684 grabbing\uFF08cursor \u6309
@@ -4308,8 +4292,11 @@ function SettingsTab({ notify, onRegistryChanged, onForceMarket, opsRecords, onO
4308
4292
  const applyAddress = async (raw) => {
4309
4293
  setApplying(true);
4310
4294
  setApplyError(null);
4295
+ const prevAddress = typeof (cfgData && cfgData.registryUrl) === "string" ? cfgData.registryUrl.trim() : "";
4311
4296
  try {
4312
4297
  await api("registry-config-apply", { registryUrl: raw });
4298
+ const to = typeof raw === "string" ? raw.trim() : "";
4299
+ recordSettingsOp("registry-url", to === "" ? REGISTRY_DEFAULT_TARGET2 : to, "done", { from: prevAddress === "" ? REGISTRY_DEFAULT_TARGET2 : prevAddress });
4313
4300
  setDraftAddress(typeof raw === "string" ? raw.trim() : "");
4314
4301
  notify({ kind: "ok", text: raw.trim() === "" ? lookup("settings.reset.ok") : lookup("settings.apply.ok"), needsRestart: false });
4315
4302
  await reloadRegistryState();
@@ -4352,11 +4339,13 @@ function SettingsTab({ notify, onRegistryChanged, onForceMarket, opsRecords, onO
4352
4339
  setCommunityBusy(true);
4353
4340
  try {
4354
4341
  await api("set-community", { enabled });
4342
+ recordSettingsOp("community-toggle", "community-catalog", "done", { on: enabled });
4355
4343
  await reloadRegistryState();
4356
4344
  await (onRegistryChanged ? onRegistryChanged() : reg.reload(false));
4357
4345
  notify({ kind: "ok", text: lookup(enabled ? "settings.community.on.ok" : "settings.community.off.ok"), needsRestart: false });
4358
4346
  } catch (e) {
4359
4347
  setCommunityOn(prev);
4348
+ recordSettingsOp("community-toggle", "community-catalog", "failed", { on: enabled }, String(e && e.message || e));
4360
4349
  notify({ kind: "err", text: lookup("settings.community.toggle.failed", { err: e && e.message || e }) });
4361
4350
  } finally {
4362
4351
  setCommunityBusy(false);
@@ -4657,6 +4646,10 @@ function FavoriteZone({ favorites, onOpen }) {
4657
4646
  var opsStore = createOperationsStore2(typeof window !== "undefined" && window.localStorage ? window.localStorage : null);
4658
4647
  var opsPumpCtx = null;
4659
4648
  var opsPump = createOpsPump2(opsStore, () => opsPumpCtx);
4649
+ function recordSettingsOp(kind, target, status, meta, error) {
4650
+ opsStore.upsert({ kind, target, status, ...meta ? { meta } : {}, ...error ? { error } : {} });
4651
+ if (opsPumpCtx && opsPumpCtx.syncOps) opsPumpCtx.syncOps();
4652
+ }
4660
4653
  var OP_STATUS_CLS = {
4661
4654
  queued: "",
4662
4655
  running: "run",
@@ -4670,12 +4663,13 @@ function OperationsCard({ records, onClearFinished, onRemove }) {
4670
4663
  const active = records.filter((r) => r.status === "queued" || r.status === "running" || r.status === "input");
4671
4664
  const finished = records.filter((r) => active.indexOf(r) < 0).slice(-50);
4672
4665
  const clearable = records.some((r) => TERMINAL_CLEARABLE2.has(r.status));
4666
+ const targetText = (r) => r.kind === "community-toggle" && r.meta && typeof r.meta.on === "boolean" ? lookup(r.meta.on ? "op.state.on" : "op.state.off") : r.target;
4673
4667
  const row = (r) => h(
4674
4668
  "div",
4675
4669
  { key: r.id, className: `dsvm-oprow ${OP_STATUS_CLS[r.status] || ""}` },
4676
4670
  h("span", { className: "dsvm-opstatus" }, lookup("op.status." + r.status)),
4677
4671
  h("span", { className: "dsvm-opkind" }, lookup("op.kind." + r.kind)),
4678
- h("span", { className: "dsvm-optarget", title: r.error || r.warning || void 0 }, r.target),
4672
+ h("span", { className: "dsvm-optarget", title: r.error || r.warning || void 0 }, targetText(r)),
4679
4673
  r.status === "running" ? Spin() : null,
4680
4674
  r.error ? h("span", { className: "dsvm-opnote" }, r.error) : null,
4681
4675
  r.warning ? h("span", { className: "dsvm-opnote" }, r.warning) : null,
@@ -4934,7 +4928,6 @@ function MarketPanel({ onClose }) {
4934
4928
  panel.classList.remove("dshm-panel--dragging");
4935
4929
  panel.style.willChange = "";
4936
4930
  panel.style.transform = "";
4937
- panel.style.removeProperty("--dshm-drag-bg");
4938
4931
  try {
4939
4932
  savePanelPos2(window.localStorage, final);
4940
4933
  } catch {
@@ -4961,7 +4954,6 @@ function MarketPanel({ onClose }) {
4961
4954
  panel.classList.remove("dshm-panel--dragging");
4962
4955
  panel.style.willChange = "";
4963
4956
  panel.style.transform = "";
4964
- panel.style.removeProperty("--dshm-drag-bg");
4965
4957
  };
4966
4958
  const onPointerDown = (event) => {
4967
4959
  if (dragging) return;
@@ -4979,9 +4971,6 @@ function MarketPanel({ onClose }) {
4979
4971
  grab = grabOffset2({ x: event.clientX, y: event.clientY }, rect);
4980
4972
  rest = { x: rect.left, y: rect.top };
4981
4973
  size = { width: rect.width, height: rect.height };
4982
- const solid = solidifyColor2(window.getComputedStyle(panel).backgroundColor);
4983
- if (solid) panel.style.setProperty("--dshm-drag-bg", solid);
4984
- else panel.style.removeProperty("--dshm-drag-bg");
4985
4974
  if (headEl.setPointerCapture) {
4986
4975
  try {
4987
4976
  headEl.setPointerCapture(event.pointerId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-m",
3
- "version": "0.9.69",
3
+ "version": "0.9.71",
4
4
  "description": "可自定义收录清单的 DSH 插件市场:收录、安装、卸载、升级一站完成,附 agent 工具与 dshm CLI。",
5
5
  "license": "MIT",
6
6
  "type": "module",