dsh-dock 0.11.1 → 0.11.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 CHANGED
@@ -95,7 +95,7 @@ dsh plugin --profile web remove dsh-dock # 卸载
95
95
  - **⛁ 会话用量**:显示当前会话的 Token 数与估算费用(10 秒自动刷新)
96
96
  - **余额**:显示当前选中模型的 Provider 账户余额(跟随模型切换实时更新)
97
97
 
98
- 点击芯片直接跳转功能坞对应页。每个功能可在面板页脚或设置页单独设置「会话页显示 / 隐藏」。
98
+ 点击芯片直接跳转功能坞对应页(「会话用量」打开后即按当前会话筛选出结果,无需再点查询)。每个功能可在面板页脚或设置页单独设置「会话页显示 / 隐藏」。
99
99
 
100
100
  ### 各功能使用
101
101
 
@@ -252,7 +252,7 @@ dsh plugin --profile web remove dsh-dock # 卸载
252
252
  - **⛁ 会话用量**:显示当前会话的 Token 数与估算费用(10 秒自动刷新)
253
253
  - **余额**:显示当前选中模型的 Provider 账户余额(跟随模型切换实时更新)
254
254
 
255
- 点击芯片直接跳转功能坞对应页。每个功能可在面板页脚或设置页单独设置「会话页显示 / 隐藏」。
255
+ 点击芯片直接跳转功能坞对应页(「会话用量」打开后即按当前会话筛选出结果,无需再点查询)。每个功能可在面板页脚或设置页单独设置「会话页显示 / 隐藏」。
256
256
 
257
257
  ### 各功能使用
258
258
 
package/client.js CHANGED
@@ -2823,6 +2823,7 @@ function PricingEditor({ onClose, onSaved, embedded }) {
2823
2823
  }
2824
2824
  function TokenLogView(props) {
2825
2825
  const navSession = props && props.params && props.params.sessionId ? props.params.sessionId : null;
2826
+ const navAt = props && props.params && props.params.navAt ? props.params.navAt : 0;
2826
2827
  const [savedFilters] = (0, import_react2.useState)(loadSavedFilters);
2827
2828
  const [fromStr, setFromStr] = (0, import_react2.useState)(() => savedFilters && savedFilters.fromStr || "");
2828
2829
  const [toStr, setToStr] = (0, import_react2.useState)(() => savedFilters && savedFilters.toStr || "");
@@ -2830,7 +2831,7 @@ function TokenLogView(props) {
2830
2831
  const [model, setModel] = (0, import_react2.useState)(() => savedFilters && savedFilters.model || "");
2831
2832
  const [status, setStatus] = (0, import_react2.useState)(() => savedFilters && savedFilters.status || "");
2832
2833
  const [effort, setEffort] = (0, import_react2.useState)(() => savedFilters && savedFilters.effort || "");
2833
- const [sessionId, setSessionId] = (0, import_react2.useState)(() => savedFilters && savedFilters.sessionId || "");
2834
+ const [sessionId, setSessionId] = (0, import_react2.useState)(() => navSession || savedFilters && savedFilters.sessionId || "");
2834
2835
  const [dim, setDim] = (0, import_react2.useState)(() => savedFilters && savedFilters.dim || "");
2835
2836
  const [sortKey, setSortKey] = (0, import_react2.useState)("time");
2836
2837
  const [sortDir, setSortDir] = (0, import_react2.useState)("desc");
@@ -2859,6 +2860,7 @@ function TokenLogView(props) {
2859
2860
  if (savedFilters.sessionId) q.sessionId = savedFilters.sessionId;
2860
2861
  if (savedFilters.dim) q.dim = savedFilters.dim;
2861
2862
  }
2863
+ if (navSession) q.sessionId = navSession;
2862
2864
  rpcCall("scan", {}).then(() => cancel ? null : rpcCall("query", q)).then((d) => {
2863
2865
  if (cancel) return;
2864
2866
  setData(d);
@@ -2892,8 +2894,10 @@ function TokenLogView(props) {
2892
2894
  setPage(0);
2893
2895
  }).catch((e) => setErr(String(e && e.message || e))).finally(() => setLoading(false));
2894
2896
  }, [buildQ]);
2897
+ const navAppliedRef = (0, import_react2.useRef)(navAt);
2895
2898
  (0, import_react2.useEffect)(() => {
2896
- if (!navSession) return;
2899
+ if (!navSession || navAppliedRef.current === navAt) return;
2900
+ navAppliedRef.current = navAt;
2897
2901
  setSessionId(navSession);
2898
2902
  setLoading(true);
2899
2903
  setErr("");
@@ -2901,7 +2905,7 @@ function TokenLogView(props) {
2901
2905
  setData(d);
2902
2906
  setPage(0);
2903
2907
  }).catch((e) => setErr(String(e && e.message || e))).finally(() => setLoading(false));
2904
- }, [navSession]);
2908
+ }, [navAt]);
2905
2909
  const resetFilters = (0, import_react2.useCallback)(() => {
2906
2910
  setFromStr("");
2907
2911
  setToStr("");
@@ -3222,7 +3226,7 @@ function TokenLogChip(props) {
3222
3226
  className: "dockchip" + (snap.err && !t ? " err" : ""),
3223
3227
  title,
3224
3228
  "aria-label": "\u4F1A\u8BDD\u7528\u91CF",
3225
- onClick: () => openPanel("tokenlog", { sessionId: sid }),
3229
+ onClick: () => openPanel("tokenlog", { sessionId: sid, navAt: Date.now() }),
3226
3230
  children: [
3227
3231
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-dot", style: { background: "var(--dk-warn)" } }),
3228
3232
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label })
@@ -10879,7 +10883,7 @@ var feature10 = {
10879
10883
  };
10880
10884
 
10881
10885
  // src/client.jsx
10882
- var DOCK_VERSION = "0.11.1";
10886
+ var DOCK_VERSION = "0.11.2";
10883
10887
  var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10];
10884
10888
  var PLANNED_FEATURES = [];
10885
10889
  var PLANNED_NOTES = {};
@@ -11039,11 +11043,14 @@ var SHELL_CSS = [
11039
11043
  // 注意:旧上限 min(280px,36cqw) 仍偏宽——标准 780px 输入卡下(.row 内容约 762px),
11040
11044
  // add 钮(28)+工作区选择器(~214)+chips(280) 已与右侧模型选择器+发送键(~345px)合计超宽,
11041
11045
  // 即便 chips 未截断 .row 也会换行把模型选择器/发送键挤到第二行。实测把上限收到 189px
11042
- // (≈25cqw)并使 chips 内距收紧(padding 2px 6px、gap 2px)后,实测 4~6M 用量 + 余额
11043
- // 两 chip 可完整显示且不再换行;超限时仍被省略号截断,完整值在 title 悬浮提示里。
11046
+ // (≈25cqw)并使 chips 内距收紧(padding 2px 6px、gap 2px)后,「4~6M 用量 + 余额」
11047
+ // 两 chip 可完整显示且不再换行。v0.11.2:配置单价后费用段「· ¥0.03」让两 chip 合计
11048
+ // 约需 204px,189px 恰好截掉约 2 个数字(费用/余额小数位看不到)——按用户反馈放宽到
11049
+ // 216px(≈28cqw),标准卡下实测完整显示;若再出现把模型选择器挤换行,优先压缩用量
11050
+ // chip 的 ⛁ 前缀换空间,别再收这个上限。超限仍省略号截断,完整值在 title 悬浮提示里。
11044
11051
  // 2) 截断:超限部分用省略号截断(完整数值在 title 悬浮提示里),防 chips 凸出输入卡圆角(悬空)。
11045
- ".dockchip-row{display:inline-flex;align-items:center;gap:2px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:189px;}",
11046
- "@supports (width:1cqw){.dockchip-row{max-width:min(189px,25cqw);}}",
11052
+ ".dockchip-row{display:inline-flex;align-items:center;gap:2px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:216px;}",
11053
+ "@supports (width:1cqw){.dockchip-row{max-width:min(216px,28cqw);}}",
11047
11054
  ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 6px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;min-width:0;overflow:hidden;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
11048
11055
  ".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
11049
11056
  ".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
@@ -531,8 +531,10 @@ function PricingEditor({ onClose, onSaved, embedded }) {
531
531
 
532
532
  // ---------- 主视图(嵌入 dock 面板内容区) ----------
533
533
  export function TokenLogView(props) {
534
- // props.params.sessionId(chips 点击带入):立即按该会话筛选并查询
534
+ // props.params.sessionId(chips 点击带入):立即按该会话筛选并查询。
535
+ // navAt:每次 chip 点击的时间戳——面板已打开时再次点击(即便同一会话)也触发重查。
535
536
  const navSession = props && props.params && props.params.sessionId ? props.params.sessionId : null;
537
+ const navAt = props && props.params && props.params.navAt ? props.params.navAt : 0;
536
538
  // 挂载即视为「打开」:恢复上次暂存的条件(时间不选=显示全部记录); savedFilters 稳定快照, 仅初始化时读取一次
537
539
  const [savedFilters] = useState(loadSavedFilters);
538
540
  const [fromStr, setFromStr] = useState(() => (savedFilters && savedFilters.fromStr) || "");
@@ -541,7 +543,8 @@ export function TokenLogView(props) {
541
543
  const [model, setModel] = useState(() => (savedFilters && savedFilters.model) || "");
542
544
  const [status, setStatus] = useState(() => (savedFilters && savedFilters.status) || "");
543
545
  const [effort, setEffort] = useState(() => (savedFilters && savedFilters.effort) || "");
544
- const [sessionId, setSessionId] = useState(() => (savedFilters && savedFilters.sessionId) || "");
546
+ // 会话入口(chip/深链)带入的 sessionId 优先于暂存条件:下拉框初值即选中该会话
547
+ const [sessionId, setSessionId] = useState(() => navSession || (savedFilters && savedFilters.sessionId) || "");
545
548
  const [dim, setDim] = useState(() => (savedFilters && savedFilters.dim) || "");
546
549
  const [sortKey, setSortKey] = useState("time");
547
550
  const [sortDir, setSortDir] = useState("desc");
@@ -575,6 +578,9 @@ export function TokenLogView(props) {
575
578
  if (savedFilters.sessionId) q.sessionId = savedFilters.sessionId;
576
579
  if (savedFilters.dim) q.dim = savedFilters.dim;
577
580
  }
581
+ // 从会话入口点入时按带入的会话查(优先于暂存条件):打开即出当前会话结果,
582
+ // 不再需要手动点「查询」。只保留这一条初始查询,避免并发的会话查询被本链路覆盖。
583
+ if (navSession) q.sessionId = navSession;
578
584
  rpcCall("scan", {})
579
585
  .then(() => (cancel ? null : rpcCall("query", q)))
580
586
  .then((d) => {
@@ -609,16 +615,20 @@ export function TokenLogView(props) {
609
615
  .finally(() => setLoading(false));
610
616
  }, [buildQ]);
611
617
 
612
- // chips 定位:按带入的会话立即筛选查询(覆盖暂存条件里的会话项)
618
+ // chips 定位:面板已打开时再次从会话入口点击 → 立即按该会话筛选查询。
619
+ // 挂载时的首次带入已并入初始查询(sessionId 初值 + 挂载 effect),以 navAt 判同跳过,
620
+ // 避免打开面板时同一条件跑两遍、且挂载查询链路较慢把会话结果覆盖回全量。
621
+ const navAppliedRef = useRef(navAt);
613
622
  useEffect(() => {
614
- if (!navSession) return;
623
+ if (!navSession || navAppliedRef.current === navAt) return;
624
+ navAppliedRef.current = navAt;
615
625
  setSessionId(navSession);
616
626
  setLoading(true); setErr("");
617
627
  rpcCall("query", Object.assign({}, buildQ(true), { sessionId: navSession }))
618
628
  .then((d) => { setData(d); setPage(0); })
619
629
  .catch((e) => setErr(String((e && e.message) || e)))
620
630
  .finally(() => setLoading(false));
621
- }, [navSession]);
631
+ }, [navAt]);
622
632
 
623
633
  // 重置: 清空所有筛选(时间不选=显示全部记录), 并立即查询
624
634
  const resetFilters = useCallback(() => { setFromStr(""); setToStr("");
@@ -902,7 +912,7 @@ export function TokenLogChip(props) {
902
912
  : (snap.err ? snap.err + "\n" : "") + "点击在功能坞查看用量记录";
903
913
  return (
904
914
  <button type="button" className={"dockchip" + (snap.err && !t ? " err" : "")} title={title} aria-label="会话用量"
905
- onClick={() => openPanel("tokenlog", { sessionId: sid })}>
915
+ onClick={() => openPanel("tokenlog", { sessionId: sid, navAt: Date.now() })}>
906
916
  <span className="dockchip-dot" style={{ background: "var(--dk-warn)" }} />
907
917
  <span>{label}</span>
908
918
  </button>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-dock",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "DeepSeek Harness 功能坞插件(dsh-dock):模块化功能中枢——每个功能一个 features/ 模块(可单独提取成包发布,又可经 dockBridge 装回面板)。含用量记录(LLM 调用记账/费用统计,支持各模型自定义单价与多段分时价)、模型设置、图片理解代理、模型余额、任务动画(19 种运行动画 + 桌面伙伴 3D 场景)、任务通知(完成/异常/需确认通知、提示音、系统通知、钉钉/飞书推送)、运行状态(进行中任务与最近完成一览);侧栏入口 + 可拖拽弹窗(最大化/最小化/缩放)。",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/src/client.jsx CHANGED
@@ -30,7 +30,7 @@ import { feature as fGames } from "../features/games/view.jsx";
30
30
  import { feature as fMobileRelay } from "../features/mobile-relay/view.jsx";
31
31
 
32
32
  const name = "dsh-dock";
33
- const DOCK_VERSION = "0.11.1";
33
+ const DOCK_VERSION = "0.11.2";
34
34
 
35
35
  // ---- 内置功能注册表:新功能 = features/<id>/ 加模块 + 这里 import 一行 ----
36
36
  const BUILTIN_FEATURES = [fTokenlog, fModelconfig, fHeartbeat, fTheme, fBalance, fAnimation, fNotify, fRunState, fGames, fMobileRelay];
@@ -206,11 +206,14 @@ const SHELL_CSS = [
206
206
  // 注意:旧上限 min(280px,36cqw) 仍偏宽——标准 780px 输入卡下(.row 内容约 762px),
207
207
  // add 钮(28)+工作区选择器(~214)+chips(280) 已与右侧模型选择器+发送键(~345px)合计超宽,
208
208
  // 即便 chips 未截断 .row 也会换行把模型选择器/发送键挤到第二行。实测把上限收到 189px
209
- // (≈25cqw)并使 chips 内距收紧(padding 2px 6px、gap 2px)后,实测 4~6M 用量 + 余额
210
- // 两 chip 可完整显示且不再换行;超限时仍被省略号截断,完整值在 title 悬浮提示里。
209
+ // (≈25cqw)并使 chips 内距收紧(padding 2px 6px、gap 2px)后,「4~6M 用量 + 余额」
210
+ // 两 chip 可完整显示且不再换行。v0.11.2:配置单价后费用段「· ¥0.03」让两 chip 合计
211
+ // 约需 204px,189px 恰好截掉约 2 个数字(费用/余额小数位看不到)——按用户反馈放宽到
212
+ // 216px(≈28cqw),标准卡下实测完整显示;若再出现把模型选择器挤换行,优先压缩用量
213
+ // chip 的 ⛁ 前缀换空间,别再收这个上限。超限仍省略号截断,完整值在 title 悬浮提示里。
211
214
  // 2) 截断:超限部分用省略号截断(完整数值在 title 悬浮提示里),防 chips 凸出输入卡圆角(悬空)。
212
- ".dockchip-row{display:inline-flex;align-items:center;gap:2px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:189px;}",
213
- "@supports (width:1cqw){.dockchip-row{max-width:min(189px,25cqw);}}",
215
+ ".dockchip-row{display:inline-flex;align-items:center;gap:2px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:216px;}",
216
+ "@supports (width:1cqw){.dockchip-row{max-width:min(216px,28cqw);}}",
214
217
  ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 6px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;min-width:0;overflow:hidden;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
215
218
  ".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
216
219
  ".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",