dsh-dock 0.11.0 → 0.11.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/client.js CHANGED
@@ -2470,9 +2470,9 @@ function Detail({ rec, onClose, rate }) {
2470
2470
  ["\u9519\u8BEF\u4FE1\u606F", rec.errorMsg || "\u2014"],
2471
2471
  ["\u9519\u8BEF\u7801", rec.errorCode || "\u2014"],
2472
2472
  ["Request ID", rec.requestId || "\u2014"],
2473
- ["\u8F93\u5165 Token(\u672A\u7F13\u5B58)", fmtNum(rec.inputTokens)],
2473
+ ["\u8F93\u5165 Token(\u7F13\u5B58\u547D\u4E2D)", fmtNum(rec.cacheReadTokens)],
2474
+ ["\u8F93\u5165 Token(\u7F13\u5B58\u672A\u547D\u4E2D)", fmtNum(rec.inputTokens)],
2474
2475
  ["\u8F93\u51FA Token", fmtNum(rec.outputTokens)],
2475
- ["\u7F13\u5B58\u547D\u4E2D Token", fmtNum(rec.cacheReadTokens)],
2476
2476
  ["\u7F13\u5B58\u5199\u5165 Token", fmtNum(rec.cacheWriteTokens)],
2477
2477
  ["\u63A8\u7406 Token", fmtNum(rec.reasoningTokens)],
2478
2478
  ["\u8BA1\u8D39\u8F93\u5165", fmtNum(rec.billedInput)],
@@ -2721,22 +2721,23 @@ function PricingEditor({ onClose, onSaved, embedded }) {
2721
2721
  ] }),
2722
2722
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-grid", children: [
2723
2723
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2724
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u8F93\u5165" }),
2724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u8F93\u5165\uFF08\u7F13\u5B58\u547D\u4E2D\uFF09" }),
2725
+ num(r.cacheRead, (v) => patchRow(i, { cacheRead: v }))
2726
+ ] }),
2727
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2728
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u8F93\u5165\uFF08\u7F13\u5B58\u672A\u547D\u4E2D\uFF09" }),
2725
2729
  num(r.input, (v) => patchRow(i, { input: v }))
2726
2730
  ] }),
2727
2731
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2728
2732
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u8F93\u51FA" }),
2729
2733
  num(r.output, (v) => patchRow(i, { output: v }))
2730
2734
  ] }),
2731
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2732
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u7F13\u5B58\u547D\u4E2D" }),
2733
- num(r.cacheRead, (v) => patchRow(i, { cacheRead: v }))
2734
- ] }),
2735
2735
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2736
2736
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u57FA\u51C6\u7F13\u5B58\u5199\u5165" }),
2737
2737
  num(r.cacheWrite, (v) => patchRow(i, { cacheWrite: v }))
2738
2738
  ] })
2739
2739
  ] }),
2740
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-price-hint", style: { marginTop: 2 }, children: "\u7F13\u5B58\u5199\u5165\uFF1D\u672A\u547D\u4E2D\u7F13\u5B58\u3001\u672C\u6B21\u65B0\u5EFA\u7F13\u5B58\u7684\u90A3\u90E8\u5206\u8F93\u5165\uFF08Claude \u7B49\u6309\u6EA2\u4EF7\u5355\u72EC\u6536\u5EFA\u7F13\u5B58\u8D39\uFF09\uFF1BDeepSeek \u4E0D\u6536\u6B64\u9879\uFF0C\u586B 0 \u5373\u53EF\u3002" }),
2740
2741
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-price-hint", style: { marginTop: 2 }, children: "\u5206\u65F6\u6BB5\u4EF7\uFF08\u53EF\u591A\u6BB5\uFF0C\u547D\u4E2D\u54EA\u6BB5\u7528\u54EA\u6BB5\uFF1B\u65F6\u6BB5\u5916\u56DE\u843D\u5230\u57FA\u51C6\u4EF7\u3002start>end \u8868\u793A\u8DE8\u96F6\u70B9\uFF0C\u5982 23~7\uFF1Bstart=end \u8868\u793A\u5168\u5929\uFF09" }),
2741
2742
  r.peaks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-price-hint", children: "\uFF08\u672A\u8BBE\u7F6E\u5206\u65F6\u6BB5\uFF0C\u6309\u57FA\u51C6\u4EF7\u8BA1\u8D39\uFF09" }) : null,
2742
2743
  r.peaks.map((s, k) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-pseg", children: [
@@ -2745,13 +2746,13 @@ function PricingEditor({ onClose, onSaved, embedded }) {
2745
2746
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtok-pseg-tilde", children: "~" }),
2746
2747
  num(s.end, (v) => patchSeg(i, k, { end: v }), { width: 56 }),
2747
2748
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtok-pseg-tilde", children: "\u65F6" }),
2748
- segNum(s.input, (v) => patchSeg(i, k, { input: v }), "\u8F93\u5165"),
2749
- segNum(s.output, (v) => patchSeg(i, k, { output: v }), "\u8F93\u51FA"),
2750
2749
  segNum(s.cacheRead, (v) => patchSeg(i, k, { cacheRead: v }), "\u7F13\u5B58\u547D\u4E2D"),
2751
- segNum(s.cacheWrite, (v) => patchSeg(i, k, { cacheWrite: v }), "\u7F13\u5B58\u5199\u5165"),
2750
+ segNum(s.input, (v) => patchSeg(i, k, { input: v }), "\u672A\u547D\u4E2D"),
2751
+ segNum(s.output, (v) => patchSeg(i, k, { output: v }), "\u8F93\u51FA"),
2752
+ segNum(s.cacheWrite, (v) => patchSeg(i, k, { cacheWrite: v }), "\u5199\u5165"),
2752
2753
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "dtok-btn tiny", onClick: () => delSeg(i, k), children: "\u5220\u9664\u65F6\u6BB5" })
2753
2754
  ] }, k)),
2754
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-price-hint", style: { opacity: 0.85 }, children: "\u65F6\u6BB5\u4EF7\u4ECE\u5DE6\u5230\u53F3\uFF1A\u8F93\u5165 / \u8F93\u51FA / \u7F13\u5B58\u547D\u4E2D / \u7F13\u5B58\u5199\u5165" }),
2755
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-price-hint", style: { opacity: 0.85 }, children: "\u65F6\u6BB5\u4EF7\u4ECE\u5DE6\u5230\u53F3\uFF1A\u8F93\u5165\uFF08\u547D\u4E2D\uFF09/ \u8F93\u5165\uFF08\u672A\u547D\u4E2D\uFF09/ \u8F93\u51FA / \u7F13\u5B58\u5199\u5165" }),
2755
2756
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "dtok-btn tiny", onClick: () => addSeg(i), children: "+ \u6DFB\u52A0\u65F6\u6BB5" })
2756
2757
  ] }, i)),
2757
2758
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-grid", style: { marginTop: 6 }, children: [
@@ -2772,17 +2773,17 @@ function PricingEditor({ onClose, onSaved, embedded }) {
2772
2773
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-section-title", style: { margin: "0 0 4px" }, children: "\u515C\u5E95\u5355\u4EF7\uFF08\u672A\u5339\u914D\u4EFB\u4F55\u6761\u76EE\u65F6\u4F7F\u7528\uFF09" }),
2773
2774
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-grid", children: [
2774
2775
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2775
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u8F93\u5165" }),
2776
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u8F93\u5165\uFF08\u7F13\u5B58\u547D\u4E2D\uFF09" }),
2777
+ num(fb.cacheRead, (v) => setFb((s) => Object.assign({}, s, { cacheRead: v })))
2778
+ ] }),
2779
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2780
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u8F93\u5165\uFF08\u7F13\u5B58\u672A\u547D\u4E2D\uFF09" }),
2776
2781
  num(fb.input, (v) => setFb((s) => Object.assign({}, s, { input: v })))
2777
2782
  ] }),
2778
2783
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2779
2784
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u8F93\u51FA" }),
2780
2785
  num(fb.output, (v) => setFb((s) => Object.assign({}, s, { output: v })))
2781
2786
  ] }),
2782
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2783
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u7F13\u5B58\u547D\u4E2D" }),
2784
- num(fb.cacheRead, (v) => setFb((s) => Object.assign({}, s, { cacheRead: v })))
2785
- ] }),
2786
2787
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtok-price-field", children: [
2787
2788
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u7F13\u5B58\u5199\u5165" }),
2788
2789
  num(fb.cacheWrite, (v) => setFb((s) => Object.assign({}, s, { cacheWrite: v })))
@@ -2798,17 +2799,17 @@ function PricingEditor({ onClose, onSaved, embedded }) {
2798
2799
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtok-table-wrap", style: { marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "dtok-table", children: [
2799
2800
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2800
2801
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u5339\u914D" }),
2801
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165" }),
2802
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165(\u547D\u4E2D)" }),
2803
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165(\u672A\u547D\u4E2D)" }),
2802
2804
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u51FA" }),
2803
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7F13\u5B58\u547D\u4E2D" }),
2804
2805
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7F13\u5B58\u5199\u5165" }),
2805
2806
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u5206\u65F6\u6BB5" })
2806
2807
  ] }) }),
2807
2808
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: cfg.builtin.map((b) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2808
2809
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.match }),
2810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.cacheRead }),
2809
2811
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.input }),
2810
2812
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.output }),
2811
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.cacheRead }),
2812
2813
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.cacheWrite }),
2813
2814
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: b.peaks && b.peaks.length ? b.peaks.map((s) => s.start + "~" + s.end).join("\u3001") + "\u65F6" : "\u2014" })
2814
2815
  ] }, b.match)) })
@@ -2969,8 +2970,8 @@ function TokenLogView(props) {
2969
2970
  const cards = totals ? [
2970
2971
  { v: fmtNum(totals.calls), l: "\u8C03\u7528\u6B21\u6570" },
2971
2972
  { v: fmtCompact(totals.totalTokens), l: "\u603B Token" },
2972
- { v: fmtCompact(totals.inputTokens), l: "\u8F93\u5165(\u672A\u7F13\u5B58)" },
2973
- { v: fmtCompact(totals.cacheReadTokens), l: "\u7F13\u5B58\u547D\u4E2D" },
2973
+ { v: fmtCompact(totals.cacheReadTokens), l: "\u8F93\u5165(\u547D\u4E2D)" },
2974
+ { v: fmtCompact(totals.inputTokens), l: "\u8F93\u5165(\u672A\u547D\u4E2D)" },
2974
2975
  { v: totals.cacheHitPct + "%", l: "\u7F13\u5B58\u547D\u4E2D\u7387" },
2975
2976
  { v: fmtCompact(totals.outputTokens), l: "\u8F93\u51FA" },
2976
2977
  { v: fmtCostCny(totals.cost, rateCny), l: "\u6D88\u8017\u91D1\u989D(\u4F30\u7B97\xB7\u4EBA\u6C11\u5E01)" },
@@ -2981,8 +2982,8 @@ function TokenLogView(props) {
2981
2982
  const summaryRows = (data && data.summary || []).map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2982
2983
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: r.key }),
2983
2984
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.calls) }),
2984
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtCompact(r.inputTokens) }),
2985
2985
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtCompact(r.cacheReadTokens) }),
2986
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtCompact(r.inputTokens) }),
2986
2987
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: r.cacheHitPct + "%" }),
2987
2988
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtCompact(r.outputTokens) }),
2988
2989
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtCompact(r.totalTokens) }),
@@ -3003,8 +3004,8 @@ function TokenLogView(props) {
3003
3004
  }, children: shortId(r.sessionId) }) }),
3004
3005
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: r.provider || "\u2014" }),
3005
3006
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: r.model || "\u2014" }),
3006
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.inputTokens) }),
3007
3007
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.cacheReadTokens) }),
3008
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.inputTokens) }),
3008
3009
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: r.cacheHitPercent + "%" }),
3009
3010
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.outputTokens) }),
3010
3011
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmtNum(r.reasoningTokens) }),
@@ -3047,8 +3048,8 @@ function TokenLogView(props) {
3047
3048
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
3048
3049
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7EF4\u5EA6" }),
3049
3050
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8C03\u7528" }),
3050
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165" }),
3051
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7F13\u5B58" }),
3051
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165(\u547D\u4E2D)" }),
3052
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165(\u672A\u547D\u4E2D)" }),
3052
3053
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u547D\u4E2D\u7387" }),
3053
3054
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u51FA" }),
3054
3055
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u603BToken" }),
@@ -3090,8 +3091,8 @@ function TokenLogView(props) {
3090
3091
  sortTh("\u4F1A\u8BDDID", "sessionId"),
3091
3092
  sortTh("\u63D0\u4F9B\u5546", "provider"),
3092
3093
  sortTh("\u6A21\u578B", "model"),
3093
- sortTh("\u8F93\u5165", "inputTokens"),
3094
- sortTh("\u7F13\u5B58", "cacheReadTokens"),
3094
+ sortTh("\u8F93\u5165(\u547D\u4E2D)", "cacheReadTokens"),
3095
+ sortTh("\u8F93\u5165(\u672A\u547D\u4E2D)", "inputTokens"),
3095
3096
  sortTh("\u547D\u4E2D%", "cacheHitPercent"),
3096
3097
  sortTh("\u8F93\u51FA", "outputTokens"),
3097
3098
  sortTh("\u63A8\u7406", "reasoningTokens"),
@@ -10878,7 +10879,7 @@ var feature10 = {
10878
10879
  };
10879
10880
 
10880
10881
  // src/client.jsx
10881
- var DOCK_VERSION = "0.11.0";
10882
+ var DOCK_VERSION = "0.11.1";
10882
10883
  var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10];
10883
10884
  var PLANNED_FEATURES = [];
10884
10885
  var PLANNED_NOTES = {};
@@ -851,7 +851,8 @@ export const feature = {
851
851
  if (method === 'export') {
852
852
  loadPricingConfig()
853
853
  const list = buildQuery(payload || {}).map(withCost)
854
- const header = ['time', 'provider', 'model', 'apiKey', 'inputTokens', 'outputTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens', 'billedInput', 'cacheHitPercent', 'totalTokens', 'costCny', 'effort', 'status', 'statusCode', 'errorCode', 'errorMsg', 'llmMs', 'sessionId', 'turn', 'step']
854
+ // 列序对齐界面习惯(缓存命中在前):… 命中 → 未命中 → 输出 → 写入
855
+ const header = ['time', 'provider', 'model', 'apiKey', 'cacheReadTokens', 'inputTokens', 'outputTokens', 'cacheWriteTokens', 'reasoningTokens', 'billedInput', 'cacheHitPercent', 'totalTokens', 'costCny', 'effort', 'status', 'statusCode', 'errorCode', 'errorMsg', 'llmMs', 'sessionId', 'turn', 'step']
855
856
  const esc = (v) => {
856
857
  const s = String(v === undefined || v === null ? '' : v)
857
858
  return /[,"\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s
@@ -189,9 +189,9 @@ function Detail({ rec, onClose, rate }) {
189
189
  ["错误信息", rec.errorMsg || "—"],
190
190
  ["错误码", rec.errorCode || "—"],
191
191
  ["Request ID", rec.requestId || "—"],
192
- ["输入 Token(未缓存)", fmtNum(rec.inputTokens)],
192
+ ["输入 Token(缓存命中)", fmtNum(rec.cacheReadTokens)],
193
+ ["输入 Token(缓存未命中)", fmtNum(rec.inputTokens)],
193
194
  ["输出 Token", fmtNum(rec.outputTokens)],
194
- ["缓存命中 Token", fmtNum(rec.cacheReadTokens)],
195
195
  ["缓存写入 Token", fmtNum(rec.cacheWriteTokens)],
196
196
  ["推理 Token", fmtNum(rec.reasoningTokens)],
197
197
  ["计费输入", fmtNum(rec.billedInput)],
@@ -451,11 +451,14 @@ function PricingEditor({ onClose, onSaved, embedded }) {
451
451
  <button className="dtok-btn tiny" onClick={() => delRow(i)}>删除模型</button>
452
452
  </div>
453
453
  <div className="dtok-price-grid">
454
- <div className="dtok-price-field"><label>基准输入</label>{num(r.input, (v) => patchRow(i, { input: v }))}</div>
454
+ <div className="dtok-price-field"><label>基准输入(缓存命中)</label>{num(r.cacheRead, (v) => patchRow(i, { cacheRead: v }))}</div>
455
+ <div className="dtok-price-field"><label>基准输入(缓存未命中)</label>{num(r.input, (v) => patchRow(i, { input: v }))}</div>
455
456
  <div className="dtok-price-field"><label>基准输出</label>{num(r.output, (v) => patchRow(i, { output: v }))}</div>
456
- <div className="dtok-price-field"><label>基准缓存命中</label>{num(r.cacheRead, (v) => patchRow(i, { cacheRead: v }))}</div>
457
457
  <div className="dtok-price-field"><label>基准缓存写入</label>{num(r.cacheWrite, (v) => patchRow(i, { cacheWrite: v }))}</div>
458
458
  </div>
459
+ <div className="dtok-price-hint" style={{ marginTop: 2 }}>
460
+ 缓存写入=未命中缓存、本次新建缓存的那部分输入(Claude 等按溢价单独收建缓存费);DeepSeek 不收此项,填 0 即可。
461
+ </div>
459
462
  <div className="dtok-price-hint" style={{ marginTop: 2 }}>
460
463
  分时段价(可多段,命中哪段用哪段;时段外回落到基准价。start&gt;end 表示跨零点,如 23~7;start=end 表示全天)
461
464
  </div>
@@ -467,14 +470,14 @@ function PricingEditor({ onClose, onSaved, embedded }) {
467
470
  <span className="dtok-pseg-tilde">~</span>
468
471
  {num(s.end, (v) => patchSeg(i, k, { end: v }), { width: 56 })}
469
472
  <span className="dtok-pseg-tilde">时</span>
470
- {segNum(s.input, (v) => patchSeg(i, k, { input: v }), "输入")}
471
- {segNum(s.output, (v) => patchSeg(i, k, { output: v }), "输出")}
472
473
  {segNum(s.cacheRead, (v) => patchSeg(i, k, { cacheRead: v }), "缓存命中")}
473
- {segNum(s.cacheWrite, (v) => patchSeg(i, k, { cacheWrite: v }), "缓存写入")}
474
+ {segNum(s.input, (v) => patchSeg(i, k, { input: v }), "未命中")}
475
+ {segNum(s.output, (v) => patchSeg(i, k, { output: v }), "输出")}
476
+ {segNum(s.cacheWrite, (v) => patchSeg(i, k, { cacheWrite: v }), "写入")}
474
477
  <button className="dtok-btn tiny" onClick={() => delSeg(i, k)}>删除时段</button>
475
478
  </div>
476
479
  ))}
477
- <div className="dtok-price-hint" style={{ opacity: .85 }}>时段价从左到右:输入 / 输出 / 缓存命中 / 缓存写入</div>
480
+ <div className="dtok-price-hint" style={{ opacity: .85 }}>时段价从左到右:输入(命中)/ 输入(未命中)/ 输出 / 缓存写入</div>
478
481
  <button className="dtok-btn tiny" onClick={() => addSeg(i)}>+ 添加时段</button>
479
482
  </div>
480
483
  ))}
@@ -492,9 +495,9 @@ function PricingEditor({ onClose, onSaved, embedded }) {
492
495
  <div>
493
496
  <div className="dtok-section-title" style={{ margin: "0 0 4px" }}>兜底单价(未匹配任何条目时使用)</div>
494
497
  <div className="dtok-price-grid">
495
- <div className="dtok-price-field"><label>输入</label>{num(fb.input, (v) => setFb((s) => Object.assign({}, s, { input: v })))}</div>
498
+ <div className="dtok-price-field"><label>输入(缓存命中)</label>{num(fb.cacheRead, (v) => setFb((s) => Object.assign({}, s, { cacheRead: v })))}</div>
499
+ <div className="dtok-price-field"><label>输入(缓存未命中)</label>{num(fb.input, (v) => setFb((s) => Object.assign({}, s, { input: v })))}</div>
496
500
  <div className="dtok-price-field"><label>输出</label>{num(fb.output, (v) => setFb((s) => Object.assign({}, s, { output: v })))}</div>
497
- <div className="dtok-price-field"><label>缓存命中</label>{num(fb.cacheRead, (v) => setFb((s) => Object.assign({}, s, { cacheRead: v })))}</div>
498
501
  <div className="dtok-price-field"><label>缓存写入</label>{num(fb.cacheWrite, (v) => setFb((s) => Object.assign({}, s, { cacheWrite: v })))}</div>
499
502
  </div>
500
503
  </div>
@@ -504,11 +507,11 @@ function PricingEditor({ onClose, onSaved, embedded }) {
504
507
  <summary className="dtok-price-hint" style={{ cursor: "pointer" }}>查看内置默认单价({cfg.builtin.length} 条,自定义配置未命中时按此兜底)</summary>
505
508
  <div className="dtok-table-wrap" style={{ marginTop: 6 }}>
506
509
  <table className="dtok-table">
507
- <thead><tr><th>匹配</th><th>输入</th><th>输出</th><th>缓存命中</th><th>缓存写入</th><th>分时段</th></tr></thead>
510
+ <thead><tr><th>匹配</th><th>输入(命中)</th><th>输入(未命中)</th><th>输出</th><th>缓存写入</th><th>分时段</th></tr></thead>
508
511
  <tbody>
509
512
  {cfg.builtin.map((b) => (
510
513
  <tr key={b.match}>
511
- <td>{b.match}</td><td>{b.input}</td><td>{b.output}</td><td>{b.cacheRead}</td><td>{b.cacheWrite}</td>
514
+ <td>{b.match}</td><td>{b.cacheRead}</td><td>{b.input}</td><td>{b.output}</td><td>{b.cacheWrite}</td>
512
515
  <td>{b.peaks && b.peaks.length ? b.peaks.map((s) => s.start + "~" + s.end).join("、") + "时" : "—"}</td>
513
516
  </tr>
514
517
  ))}
@@ -684,8 +687,8 @@ export function TokenLogView(props) {
684
687
  const cards = totals ? [
685
688
  { v: fmtNum(totals.calls), l: "调用次数" },
686
689
  { v: fmtCompact(totals.totalTokens), l: "总 Token" },
687
- { v: fmtCompact(totals.inputTokens), l: "输入(未缓存)" },
688
- { v: fmtCompact(totals.cacheReadTokens), l: "缓存命中" },
690
+ { v: fmtCompact(totals.cacheReadTokens), l: "输入(命中)" },
691
+ { v: fmtCompact(totals.inputTokens), l: "输入(未命中)" },
689
692
  { v: totals.cacheHitPct + "%", l: "缓存命中率" },
690
693
  { v: fmtCompact(totals.outputTokens), l: "输出" },
691
694
  { v: fmtCostCny(totals.cost, rateCny), l: "消耗金额(估算·人民币)" },
@@ -702,8 +705,8 @@ export function TokenLogView(props) {
702
705
 
703
706
  const summaryRows = (data && data.summary || []).map((r) => (
704
707
  <tr key={r.key}>
705
- <td>{r.key}</td><td>{fmtNum(r.calls)}</td><td>{fmtCompact(r.inputTokens)}</td>
706
- <td>{fmtCompact(r.cacheReadTokens)}</td><td>{r.cacheHitPct + "%"}</td><td>{fmtCompact(r.outputTokens)}</td>
708
+ <td>{r.key}</td><td>{fmtNum(r.calls)}</td><td>{fmtCompact(r.cacheReadTokens)}</td>
709
+ <td>{fmtCompact(r.inputTokens)}</td><td>{r.cacheHitPct + "%"}</td><td>{fmtCompact(r.outputTokens)}</td>
707
710
  <td>{fmtCompact(r.totalTokens)}</td>
708
711
  <td>{fmtCostCny(r.cost, rateCny)}</td>
709
712
  <td>{fmtDuration(r.llmMs)}</td>
@@ -724,8 +727,8 @@ export function TokenLogView(props) {
724
727
  <td><span className="dtok-sid" title="点击按此会话筛选" onClick={() => { setSessionId(r.sessionId); runQuery(); }}>{shortId(r.sessionId)}</span></td>
725
728
  <td>{r.provider || "—"}</td>
726
729
  <td>{r.model || "—"}</td>
727
- <td>{fmtNum(r.inputTokens)}</td>
728
730
  <td>{fmtNum(r.cacheReadTokens)}</td>
731
+ <td>{fmtNum(r.inputTokens)}</td>
729
732
  <td>{r.cacheHitPercent + "%"}</td>
730
733
  <td>{fmtNum(r.outputTokens)}</td>
731
734
  <td>{fmtNum(r.reasoningTokens)}</td>
@@ -756,7 +759,7 @@ export function TokenLogView(props) {
756
759
  <div key="sumtab" className="dtok-table-wrap">
757
760
  <table className="dtok-table">
758
761
  <thead><tr>
759
- <th>维度</th><th>调用</th><th>输入</th><th>缓存</th><th>命中率</th><th>输出</th><th>总Token</th><th>金额(人民币)</th><th>耗时</th>
762
+ <th>维度</th><th>调用</th><th>输入(命中)</th><th>输入(未命中)</th><th>命中率</th><th>输出</th><th>总Token</th><th>金额(人民币)</th><th>耗时</th>
760
763
  </tr></thead>
761
764
  <tbody>{summaryRows}</tbody>
762
765
  </table>
@@ -788,7 +791,7 @@ export function TokenLogView(props) {
788
791
  <table className="dtok-table">
789
792
  <thead><tr>
790
793
  {sortTh("时间", "time")}{sortTh("会话ID", "sessionId")}{sortTh("提供商", "provider")}{sortTh("模型", "model")}
791
- {sortTh("输入", "inputTokens")}{sortTh("缓存", "cacheReadTokens")}{sortTh("命中%", "cacheHitPercent")}{sortTh("输出", "outputTokens")}
794
+ {sortTh("输入(命中)", "cacheReadTokens")}{sortTh("输入(未命中)", "inputTokens")}{sortTh("命中%", "cacheHitPercent")}{sortTh("输出", "outputTokens")}
792
795
  {sortTh("推理", "reasoningTokens")}{sortTh("总额", "totalTokens")}{sortTh("金额(人民币)", "cost")}{sortTh("强度", "effort")}
793
796
  {sortTh("状态", "status")}{sortTh("耗时", "llmMs")}
794
797
  </tr></thead>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-dock",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
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.0";
33
+ const DOCK_VERSION = "0.11.1";
34
34
 
35
35
  // ---- 内置功能注册表:新功能 = features/<id>/ 加模块 + 这里 import 一行 ----
36
36
  const BUILTIN_FEATURES = [fTokenlog, fModelconfig, fHeartbeat, fTheme, fBalance, fAnimation, fNotify, fRunState, fGames, fMobileRelay];