dsh-context-actions 0.1.0 → 0.1.1

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
@@ -2,6 +2,16 @@
2
2
 
3
3
  本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 与 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.1.1] - 2026-09-15
6
+
7
+ ### Fixed
8
+
9
+ - 「压缩 / 交接」按钮不再注入「会话统计 / 本轮用量 / 本轮用时 / tok 统计」等其它浮窗,只在上下文圆环(ContextMeter)面板中出现。
10
+
11
+ ### Changed
12
+
13
+ - 「压缩 / 交接」按钮改为透明底 + 细边框 + `backdrop-filter` 毛玻璃样式,与上下文面板的原生圆角/层级保持一致。
14
+
5
15
  ## [0.1.0] - 2026-09-15
6
16
 
7
17
  ### Added
package/lib/client.js CHANGED
@@ -160,11 +160,13 @@ window.__ModuleLoader__.load({
160
160
  let t = (key) => DICTS.zh[key] ?? key;
161
161
 
162
162
  const CSS = [
163
- '.dsch-box{display:flex;flex-direction:column;gap:8px;margin-top:10px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.28))}',
163
+ '.dsch-box{display:flex;flex-direction:column;gap:8px;margin-top:10px;padding-top:10px;border-top:.5px solid var(--dsw-alias-border-l2,rgba(128,128,128,.24))}',
164
164
  '.dsch-row{display:flex;gap:8px}',
165
- '.dsch-btn{flex:1 1 0;min-width:0;height:26px;display:inline-flex;align-items:center;justify-content:center;padding:0 8px;font:inherit;font-size:12px;line-height:1;color:var(--dsw-alias-label-primary,inherit);background:var(--dsw-alias-button-tool-bar-fill,rgba(128,128,128,.12));border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.28));border-radius:8px;cursor:pointer}',
166
- '.dsch-btn:hover:not(:disabled){background:var(--dsw-alias-button-tool-bar-hover,rgba(128,128,128,.2))}',
167
- '.dsch-btn:disabled{opacity:.5;cursor:default}',
165
+ '.dsch-btn{position:relative;flex:1 1 0;min-width:0;height:28px;display:inline-flex;align-items:center;justify-content:center;padding:0 12px;font:inherit;font-size:12px;font-weight:500;line-height:1;color:var(--dsw-alias-label-primary,inherit);background:rgba(127,127,127,.12);background:color-mix(in srgb,var(--dsw-alias-bg-layer-3,#808080) 42%,transparent);border:1px solid rgba(127,127,127,.3);border-color:color-mix(in srgb,var(--dsw-alias-border-l2,#808080) 72%,transparent);border-radius:10px;-webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);box-shadow:0 1px 2px rgba(0,0,0,.06),inset 0 1px 0 rgba(255,255,255,.12);cursor:pointer;transition:background .16s ease,border-color .16s ease,box-shadow .16s ease,transform .12s ease}',
166
+ '.dsch-btn:hover:not(:disabled){background:rgba(127,127,127,.2);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#808080) 58%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-label-dimmed,#808080) 58%,transparent);box-shadow:0 2px 6px rgba(0,0,0,.1),inset 0 1px 0 rgba(255,255,255,.16)}',
167
+ '.dsch-btn:active:not(:disabled){transform:translateY(1px);background:rgba(127,127,127,.24)}',
168
+ '.dsch-btn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4c8dff);outline-offset:2px}',
169
+ '.dsch-btn:disabled{opacity:.45;cursor:default;box-shadow:none}',
168
170
  '.dsch-status{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary,inherit);word-break:break-all}',
169
171
  '.dsch-status:empty{display:none}',
170
172
  '.dsch-status[data-kind="ok"]{color:var(--dsw-alias-state-success-primary,inherit)}',
@@ -272,7 +274,7 @@ window.__ModuleLoader__.load({
272
274
 
273
275
  /** 页面结构变化后把按钮容器对到面板末尾。 */
274
276
  function sync() {
275
- const panel = findPanel();
277
+ const panel = findContextPanel(document);
276
278
  if (panel === null) {
277
279
  if (ui.box !== null && !document.contains(ui.box)) removeBox();
278
280
  return;
@@ -282,27 +284,6 @@ window.__ModuleLoader__.load({
282
284
  if (ui.panel === panel && panel.lastElementChild !== ui.box) panel.appendChild(ui.box);
283
285
  }
284
286
 
285
- /** 找到「上下文已用」面板。 */
286
- function findPanel() {
287
- const triggers = document.querySelectorAll('button[aria-haspopup="dialog"][aria-expanded="true"]');
288
- for (const trigger of triggers) {
289
- const label = trigger.getAttribute('aria-label') || '';
290
- if (!/\d\s*%/.test(label)) continue; // 语义无关的锚点:读数里一定带百分号
291
- let node = trigger.parentElement;
292
- for (let depth = 0; depth < 4 && node !== null; depth += 1, node = node.parentElement) {
293
- for (const child of node.children) {
294
- if (child.getAttribute('role') === 'dialog') return child;
295
- }
296
- }
297
- }
298
- // 结构兜底:带三行图例(dt/dd)的 dialog 就是上下文面板。
299
- for (const dialog of document.querySelectorAll('div[role="dialog"]')) {
300
- const list = dialog.querySelector('dl');
301
- if (list !== null && list.querySelectorAll('dt').length >= 3) return dialog;
302
- }
303
- return null;
304
- }
305
-
306
287
  /** 在指定面板里创建按钮容器。 */
307
288
  function ensureBox(panel) {
308
289
  if (ui.box !== null && ui.panel === panel && panel.contains(ui.box)) return;
@@ -542,6 +523,37 @@ window.__ModuleLoader__.load({
542
523
  * 纯函数工具
543
524
  * ---------------------------------------------------------------- */
544
525
 
526
+ /**
527
+ * 找到「上下文已用」圆环打开的面板;找不到返回 null。
528
+ *
529
+ * 只认 dsh 的 ContextMeter 这个 trigger:
530
+ * - aria-haspopup="dialog" 且 aria-expanded="true"
531
+ * - aria-label 带百分比读数(zh「上下文已用 45%」/ en「45% of context used」)
532
+ * - 且能证明是上下文读数:aria-label 含「上下文 / context」,或 trigger 里是 14×14 的圆环 SVG
533
+ *
534
+ * 上下文面板就渲染在 trigger 的祖先节点里(inline,不是 portal),最多向上找 4 层。
535
+ * 这里刻意不做「任意 role=dialog + dt/dd」的兜底:那会把「会话统计 / 本轮用量 / 本轮用时」
536
+ * 等浮窗也当成上下文面板。
537
+ */
538
+ function findContextPanel(documentRef) {
539
+ const triggers = documentRef.querySelectorAll('button[aria-haspopup="dialog"][aria-expanded="true"]');
540
+ for (const trigger of triggers) {
541
+ const label = trigger.getAttribute('aria-label') || '';
542
+ if (!/\d\s*%/.test(label)) continue;
543
+ const isContextReading =
544
+ /(?:上下文|context)/i.test(label) || trigger.querySelector('svg[viewBox="0 0 14 14"]') !== null;
545
+ if (!isContextReading) continue;
546
+ let node = trigger.parentElement;
547
+ for (let depth = 0; depth < 4 && node !== null; depth += 1, node = node.parentElement) {
548
+ const children = node.children === undefined ? [] : node.children;
549
+ for (const child of children) {
550
+ if (child.getAttribute('role') === 'dialog') return child;
551
+ }
552
+ }
553
+ }
554
+ return null;
555
+ }
556
+
545
557
  /** 注入按钮样式(幂等)。 */
546
558
  function ensureStyles() {
547
559
  if (document.querySelector('style[data-dsh-context-actions]') !== null) return;
@@ -997,6 +1009,8 @@ window.__ModuleLoader__.load({
997
1009
  );
998
1010
  }
999
1011
 
1012
+ exports.__test = { findContextPanel };
1013
+
1000
1014
  exports.name = NAME;
1001
1015
  exports.apply = apply;
1002
1016
  return module.exports;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context-actions",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "DeepSeek Harness(dsh)Web GUI 插件:在上下文占用面板新增「压缩」与「交接」按钮。Adds Compact / Handover buttons to the dsh context panel (unofficial plugin).",
5
5
  "keywords": [
6
6
  "dsh",