zcode-pro 1.2.1 → 1.3.0

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/dist/inject.js CHANGED
@@ -286,20 +286,19 @@
286
286
  featureNewtabPanelsDesc: "\u5B98\u65B9\u201C\u65B0\u6807\u7B7E\u9875\u201D\u53EA\u5217\u5B98\u65B9\u9762\u677F\u4E0E\u63A8\u8350\u7684\u5B98\u65B9\u63D2\u4EF6\uFF0C\u6B64\u529F\u80FD\u628A\u7B2C\u4E09\u65B9\u5E02\u573A\u63D2\u4EF6\uFF08headroom\u3001rtk \u7B49\uFF09\u7684\u9762\u677F\u5361\u7247\u52A0\u8FDB\u53BB\uFF0C\u70B9\u51FB\u5728\u4FA7\u8FB9\u9762\u677F\u6253\u5F00\u3002",
287
287
  ntpDescSuffix: "\u63D2\u4EF6\u9762\u677F",
288
288
  ntpNeedSession: "\u5148\u6253\u5F00\u4E00\u4E2A\u4EFB\u52A1\u4F1A\u8BDD\uFF0C\u518D\u4ECE\u65B0\u6807\u7B7E\u9875\u6253\u5F00\u63D2\u4EF6\u9762\u677F",
289
- featureStatusBar: "\u72B6\u6001\u680F\u7EDF\u8BA1",
290
289
  featureStatusBarDesc: "\u4E3B\u754C\u9762\u5E95\u90E8\u53F3\u4E0B\u89D2\u663E\u793A\u7EDF\u8BA1\u9879\uFF1A\u4E0A\u4E0B\u6587\u5360\u7528\u3001\u4F1A\u8BDD/\u4ECA\u65E5/\u7D2F\u8BA1 token\u3001\u4EFB\u52A1\u6570\u7B49\uFF1B\u5404\u9879\u7684\u987A\u5E8F\u4E0E\u663E\u9690\u5728\u201C\u6837\u5F0F \u2192 \u72B6\u6001\u680F\u201D\u91CC\u8C03\u6574\u3002",
291
290
  tabStylesPane: "\u6837\u5F0F\u8C03\u6574",
292
291
  tabStatusPane: "\u72B6\u6001\u680F",
293
292
  sbItemCtx: "\u4E0A\u4E0B\u6587\u5360\u7528",
294
293
  sbItemQuestions: "\u63D0\u95EE\u6B21\u6570",
294
+ sbMaster: "\u542F\u7528\u7EDF\u8BA1",
295
+ sbMasterDesc: "\u603B\u5F00\u5173\uFF1A\u5173\u95ED\u540E\u5E95\u90E8\u72B6\u6001\u680F\u4E0E\u6BCF\u8F6E\u56DE\u7B54\u7684\u7528\u91CF\u6807\u6CE8\u4E00\u8D77\u505C\u7528\u3002",
295
296
  sbGroupSession: "\u4F1A\u8BDD\u7EDF\u8BA1\uFF08\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\uFF09",
296
297
  sbGroupGlobal: "\u603B\u7EDF\u8BA1",
297
298
  sbGroupTurn: "\u6BCF\u8F6E\u7EDF\u8BA1\uFF08\u56DE\u7B54\u672B\u5C3E\uFF09",
298
299
  sbLabelIn: "\u8F93\u5165",
299
300
  sbLabelOut: "\u8F93\u51FA",
300
301
  sbLabelCache: "\u7F13\u5B58",
301
- featureTurnUsage: "\u6BCF\u8F6E\u56DE\u7B54 token \u7528\u91CF",
302
- featureTurnUsageDesc: "\u5728\u6BCF\u6761\u56DE\u7B54\u672B\u5C3E\u64CD\u4F5C\u6309\u94AE\u7684\u65F6\u95F4\u540E\u9762\u663E\u793A\u8BE5\u8F6E\u7684\u8F93\u5165/\u8F93\u51FA token\uFF08\u672C\u5730\u8BB0\u5F55\u53EA\u4FDD\u7559\u6700\u8FD1\u82E5\u5E72\u8F6E\uFF0C\u5BF9\u4E0D\u4E0A\u65F6\u95F4\u7684\u65E7\u56DE\u7B54\u4E0D\u663E\u793A\uFF09\u3002",
303
302
  turnUsageTitle: "\u672C\u8F6E token",
304
303
  sbLabelQuestions: "\u63D0\u95EE",
305
304
  sbItemTodayTokens: "\u4ECA\u65E5 token",
@@ -743,20 +742,19 @@
743
742
  featureNewtabPanelsDesc: 'The built-in "new tab page" only lists built-in panels and recommended official plugins; this adds cards for third-party marketplace plugin panels (headroom, rtk, \u2026) that open in the side pane.',
744
743
  ntpDescSuffix: "plugin panel",
745
744
  ntpNeedSession: "Open a task session first, then open plugin panels from the new tab page",
746
- featureStatusBar: "Status bar statistics",
747
745
  featureStatusBarDesc: 'Shows statistics at the bottom-right of the main view: context usage, session/today/total tokens, task count, etc.; reorder or hide each item under "Styles \u2192 Status bar".',
748
746
  tabStylesPane: "Styles",
749
747
  tabStatusPane: "Status bar",
750
748
  sbItemCtx: "Context usage",
751
749
  sbItemQuestions: "Questions asked",
750
+ sbMaster: "Enable statistics",
751
+ sbMasterDesc: "Master switch: turning this off disables both the status bar and per-turn labels.",
752
752
  sbGroupSession: "Session statistics (follows current session)",
753
753
  sbGroupGlobal: "Global statistics",
754
754
  sbGroupTurn: "Per-turn statistics (answer rows)",
755
755
  sbLabelIn: "in",
756
756
  sbLabelOut: "out",
757
757
  sbLabelCache: "cache",
758
- featureTurnUsage: "Per-turn token usage",
759
- featureTurnUsageDesc: "Shows that turn's in/out tokens after the time in each answer's action row (local records keep only the most recent turns; older answers without a match stay unlabelled).",
760
758
  turnUsageTitle: "Turn tokens",
761
759
  sbLabelQuestions: "asks",
762
760
  sbItemTodayTokens: "Today tokens",
@@ -4163,16 +4161,6 @@
4163
4161
  if (await setFeature("newtabPanels", next)) f.newtabPanels = next;
4164
4162
  refreshRows();
4165
4163
  }),
4166
- settingRow(L.featureStatusBar, L.featureStatusBarDesc, f.statusBar !== false, async () => {
4167
- const next = !(f.statusBar !== false);
4168
- if (await setFeature("statusBar", next)) f.statusBar = next;
4169
- refreshRows();
4170
- }),
4171
- settingRow(L.featureTurnUsage, L.featureTurnUsageDesc, f.turnUsage !== false, async () => {
4172
- const next = !(f.turnUsage !== false);
4173
- if (await setFeature("turnUsage", next)) f.turnUsage = next;
4174
- refreshRows();
4175
- }),
4176
4164
  (() => {
4177
4165
  const repoLink = h("span", {
4178
4166
  class: "cursor-pointer underline-offset-4 hover:underline",
@@ -4717,8 +4705,30 @@
4717
4705
  renderGroup(sbGlobalList, STATUS_GLOBAL_IDS);
4718
4706
  };
4719
4707
  renderSbItems();
4708
+ const sbPaneRerender = () => {
4709
+ renderSbItems();
4710
+ };
4711
+ let masterRow = null;
4712
+ const renderMaster = () => {
4713
+ const next = masterRow ? !((config.features || {}).statusBar !== false) : (config.features || {}).statusBar !== false;
4714
+ const fresh = settingRow(L.sbMaster, L.sbMasterDesc, (config.features || {}).statusBar !== false, async () => {
4715
+ const to = !((config.features || {}).statusBar !== false);
4716
+ const res = await rpc("/config", { method: "POST", body: { features: { statusBar: to } } });
4717
+ clearConfigCache();
4718
+ if (res.ok) {
4719
+ config.features = { ...config.features || {}, statusBar: to };
4720
+ }
4721
+ window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
4722
+ renderMaster();
4723
+ });
4724
+ fresh.setAttribute("data-zcodepro-sb-master", "1");
4725
+ if (masterRow) masterRow.replaceWith(fresh);
4726
+ masterRow = fresh;
4727
+ };
4728
+ renderMaster();
4720
4729
  paneStylesSub2.append(
4721
- h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.featureStatusBarDesc),
4730
+ masterRow,
4731
+ h("p", { class: "mt-2 text-ui-sm/relaxed text-foreground-subtle" }, L.featureStatusBarDesc),
4722
4732
  h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupSession),
4723
4733
  sbList,
4724
4734
  h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupGlobal),
@@ -8323,13 +8333,13 @@
8323
8333
  }
8324
8334
  function startTurnUsage() {
8325
8335
  void getConfig().then((cfg) => {
8326
- enabled5 = cfg.features ? cfg.features.turnUsage !== false : true;
8336
+ enabled5 = cfg.features ? cfg.features.statusBar !== false : true;
8327
8337
  }).catch(() => {
8328
8338
  });
8329
8339
  refreshTurnItems();
8330
8340
  window.addEventListener("zcodepro:config-changed", () => {
8331
8341
  void getConfig().then((cfg) => {
8332
- enabled5 = cfg.features ? cfg.features.turnUsage !== false : true;
8342
+ enabled5 = cfg.features ? cfg.features.statusBar !== false : true;
8333
8343
  }).catch(() => {
8334
8344
  });
8335
8345
  refreshTurnItems();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zcode-pro",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "ZCode Pro — 为 ZCode 桌面版增加界面增强(不修改客户端文件,通过 ZCode Pro 快捷方式启动即可),核心功能:项目自定义别名",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@ import { reorderWorkspaceTasks, reorderGroupMembers } from './taskOrder.mjs';
17
17
  import { webdavRequest, webdavPutWithMkcol, webdavHttpText, parseWebdavListing, findCurl } from './webdav.mjs';
18
18
  import { resolveZcodeExecutable } from './paths.mjs';
19
19
 
20
- const VERSION = '1.2.1';
20
+ const VERSION = '1.3.0';
21
21
 
22
22
  // 全局提示词固定在用户主目录:官方加载器按 HOME/USERPROFILE 拼 .zcode/AGENTS.md,
23
23
  // 不读 ZCODE_DATA_BASE_DIR(数据根迁走时全局指令仍在原位)。
@@ -1829,8 +1829,12 @@ export function mergeAliases(localRaw, remoteRaw) {
1829
1829
  function applyFeaturesPartial(base, partial) {
1830
1830
  const out = (base && typeof base === 'object') ? base : {};
1831
1831
  if (!partial || typeof partial !== 'object') return out;
1832
- for (const key of Object.keys(defaultConfig().features)) {
1832
+ const known = new Set(Object.keys(defaultConfig().features));
1833
+ for (const key of Object.keys(partial)) {
1834
+ // 布尔特性一律可存(新特性未列入 defaultConfig 时不能被丢弃),
1835
+ // 非布尔值只在已知键内接受
1833
1836
  if (typeof partial[key] === 'boolean') out[key] = partial[key];
1837
+ else if (known.has(key)) out[key] = partial[key];
1834
1838
  }
1835
1839
  return out;
1836
1840
  }
@@ -296,20 +296,19 @@ const zh = {
296
296
  featureNewtabPanelsDesc: '官方“新标签页”只列官方面板与推荐的官方插件,此功能把第三方市场插件(headroom、rtk 等)的面板卡片加进去,点击在侧边面板打开。',
297
297
  ntpDescSuffix: '插件面板',
298
298
  ntpNeedSession: '先打开一个任务会话,再从新标签页打开插件面板',
299
- featureStatusBar: '状态栏统计',
300
299
  featureStatusBarDesc: '主界面底部右下角显示统计项:上下文占用、会话/今日/累计 token、任务数等;各项的顺序与显隐在“样式 → 状态栏”里调整。',
301
300
  tabStylesPane: '样式调整',
302
301
  tabStatusPane: '状态栏',
303
302
  sbItemCtx: '上下文占用',
304
303
  sbItemQuestions: '提问次数',
304
+ sbMaster: '启用统计',
305
+ sbMasterDesc: '总开关:关闭后底部状态栏与每轮回答的用量标注一起停用。',
305
306
  sbGroupSession: '会话统计(跟随当前会话)',
306
307
  sbGroupGlobal: '总统计',
307
308
  sbGroupTurn: '每轮统计(回答末尾)',
308
309
  sbLabelIn: '输入',
309
310
  sbLabelOut: '输出',
310
311
  sbLabelCache: '缓存',
311
- featureTurnUsage: '每轮回答 token 用量',
312
- featureTurnUsageDesc: '在每条回答末尾操作按钮的时间后面显示该轮的输入/输出 token(本地记录只保留最近若干轮,对不上时间的旧回答不显示)。',
313
312
  turnUsageTitle: '本轮 token',
314
313
  sbLabelQuestions: '提问',
315
314
  sbItemTodayTokens: '今日 token',
@@ -754,20 +753,19 @@ const en = {
754
753
  featureNewtabPanelsDesc: "The built-in \"new tab page\" only lists built-in panels and recommended official plugins; this adds cards for third-party marketplace plugin panels (headroom, rtk, …) that open in the side pane.",
755
754
  ntpDescSuffix: 'plugin panel',
756
755
  ntpNeedSession: 'Open a task session first, then open plugin panels from the new tab page',
757
- featureStatusBar: 'Status bar statistics',
758
756
  featureStatusBarDesc: 'Shows statistics at the bottom-right of the main view: context usage, session/today/total tokens, task count, etc.; reorder or hide each item under "Styles → Status bar".',
759
757
  tabStylesPane: 'Styles',
760
758
  tabStatusPane: 'Status bar',
761
759
  sbItemCtx: 'Context usage',
762
760
  sbItemQuestions: 'Questions asked',
761
+ sbMaster: 'Enable statistics',
762
+ sbMasterDesc: 'Master switch: turning this off disables both the status bar and per-turn labels.',
763
763
  sbGroupSession: 'Session statistics (follows current session)',
764
764
  sbGroupGlobal: 'Global statistics',
765
765
  sbGroupTurn: 'Per-turn statistics (answer rows)',
766
766
  sbLabelIn: 'in',
767
767
  sbLabelOut: 'out',
768
768
  sbLabelCache: 'cache',
769
- featureTurnUsage: 'Per-turn token usage',
770
- featureTurnUsageDesc: "Shows that turn's in/out tokens after the time in each answer's action row (local records keep only the most recent turns; older answers without a match stay unlabelled).",
771
769
  turnUsageTitle: 'Turn tokens',
772
770
  sbLabelQuestions: 'asks',
773
771
  sbItemTodayTokens: 'Today tokens',
@@ -375,16 +375,6 @@ export function openSettingsDialog() {
375
375
  if (await setFeature('newtabPanels', next)) f.newtabPanels = next;
376
376
  refreshRows();
377
377
  }),
378
- settingRow(L.featureStatusBar, L.featureStatusBarDesc, f.statusBar !== false, async () => {
379
- const next = !(f.statusBar !== false);
380
- if (await setFeature('statusBar', next)) f.statusBar = next;
381
- refreshRows();
382
- }),
383
- settingRow(L.featureTurnUsage, L.featureTurnUsageDesc, f.turnUsage !== false, async () => {
384
- const next = !(f.turnUsage !== false);
385
- if (await setFeature('turnUsage', next)) f.turnUsage = next;
386
- refreshRows();
387
- }),
388
378
  (() => {
389
379
  // 标题 = “自动更新 duanluan/zcode-plugins 插件”,仓库名可点击跳转仓库
390
380
  const repoLink = h('span', {
@@ -840,8 +830,28 @@ export function openSettingsDialog() {
840
830
  renderGroup(sbGlobalList, STATUS_GLOBAL_IDS);
841
831
  };
842
832
  renderSbItems();
833
+ const sbPaneRerender = () => { renderSbItems(); };
834
+ // 总开关:与其它设置行完全同款 settingRow(自带开关样式);保存成功后
835
+ // 重建该行让开关视觉立即跟随
836
+ let masterRow = null;
837
+ const renderMaster = () => {
838
+ const next = masterRow ? !((config.features || {}).statusBar !== false) : ((config.features || {}).statusBar !== false);
839
+ const fresh = settingRow(L.sbMaster, L.sbMasterDesc, (config.features || {}).statusBar !== false, async () => {
840
+ const to = !((config.features || {}).statusBar !== false);
841
+ const res = await rpc('/config', { method: 'POST', body: { features: { statusBar: to } } });
842
+ clearConfigCache();
843
+ if (res.ok) { config.features = { ...(config.features || {}), statusBar: to }; }
844
+ window.dispatchEvent(new CustomEvent('zcodepro:config-changed'));
845
+ renderMaster();
846
+ });
847
+ fresh.setAttribute('data-zcodepro-sb-master', '1');
848
+ if (masterRow) masterRow.replaceWith(fresh);
849
+ masterRow = fresh;
850
+ };
851
+ renderMaster();
843
852
  paneStylesSub2.append(
844
- h('p', { class: 'text-ui-sm/relaxed text-foreground-subtle' }, L.featureStatusBarDesc),
853
+ masterRow,
854
+ h('p', { class: 'mt-2 text-ui-sm/relaxed text-foreground-subtle' }, L.featureStatusBarDesc),
845
855
  h('div', { class: 'mt-3 mb-1 text-ui-sm font-medium' }, L.sbGroupSession),
846
856
  sbList,
847
857
  h('div', { class: 'mt-3 mb-1 text-ui-sm font-medium' }, L.sbGroupGlobal),
@@ -178,10 +178,10 @@ async function tick() {
178
178
  }
179
179
 
180
180
  export function startTurnUsage() {
181
- void getConfig().then((cfg) => { enabled = cfg.features ? cfg.features.turnUsage !== false : true; }).catch(() => {});
181
+ void getConfig().then((cfg) => { enabled = cfg.features ? cfg.features.statusBar !== false : true; }).catch(() => {});
182
182
  refreshTurnItems();
183
183
  window.addEventListener('zcodepro:config-changed', () => {
184
- void getConfig().then((cfg) => { enabled = cfg.features ? cfg.features.turnUsage !== false : true; }).catch(() => {});
184
+ void getConfig().then((cfg) => { enabled = cfg.features ? cfg.features.statusBar !== false : true; }).catch(() => {});
185
185
  refreshTurnItems();
186
186
  });
187
187
  // 回答行出现即注入(去抖);数据 5 秒刷新一次