zcode-pro 1.2.0 → 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/README.en.md +3 -0
- package/README.md +3 -0
- package/dist/inject.js +996 -84
- package/package.json +1 -1
- package/src/host/helper.mjs +179 -5
- package/src/host/taskIndex.mjs +18 -0
- package/src/inject/core.js +86 -0
- package/src/inject/features/plugin-card-retry.js +48 -0
- package/src/inject/features/sandbox-reclaim.js +49 -20
- package/src/inject/features/settings-dialog.js +156 -3
- package/src/inject/features/status-bar.js +274 -0
- package/src/inject/features/turn-usage.js +195 -0
- package/src/inject/index.js +8 -0
- package/src/inject/ui.js +50 -0
package/dist/inject.js
CHANGED
|
@@ -42,6 +42,28 @@
|
|
|
42
42
|
switchAttention: "r"
|
|
43
43
|
// 打开运行中 / 未查看
|
|
44
44
|
};
|
|
45
|
+
var STATUS_SESSION_IDS = /* @__PURE__ */ new Set(["ctx", "sessionCost", "questions"]);
|
|
46
|
+
var STATUS_GLOBAL_IDS = /* @__PURE__ */ new Set(["todayTokens", "todayCost", "totalTokens", "totalCost", "tasks"]);
|
|
47
|
+
var DEFAULT_TURN_ITEMS = [
|
|
48
|
+
{ id: "turnIn", on: true },
|
|
49
|
+
// 输入
|
|
50
|
+
{ id: "turnOut", on: true },
|
|
51
|
+
// 输出
|
|
52
|
+
{ id: "turnCache", on: true }
|
|
53
|
+
// 缓存命中率
|
|
54
|
+
];
|
|
55
|
+
var DEFAULT_STATUS_ITEMS = [
|
|
56
|
+
{ id: "ctx", on: true },
|
|
57
|
+
// 上下文占用
|
|
58
|
+
{ id: "questions", on: true },
|
|
59
|
+
// 提问次数
|
|
60
|
+
{ id: "todayTokens", on: true },
|
|
61
|
+
// 今日 token(今天的会话记录完整,数据准确)
|
|
62
|
+
{ id: "totalTokens", on: true },
|
|
63
|
+
// 累计 token(官方使用统计,全历史)
|
|
64
|
+
{ id: "tasks", on: true }
|
|
65
|
+
// 任务总数
|
|
66
|
+
];
|
|
45
67
|
function zcodeAppVersion() {
|
|
46
68
|
const v = liveBoot().zcodeVersion;
|
|
47
69
|
return typeof v === "string" && v ? v : "";
|
|
@@ -235,6 +257,11 @@
|
|
|
235
257
|
tbPluginStore: "\u63D2\u4EF6\u5E02\u573A",
|
|
236
258
|
featurePinnedCollapse: "\u5DF2\u7F6E\u9876\u5206\u533A\u53EF\u6298\u53E0",
|
|
237
259
|
featurePinnedCollapseDesc: "\u4FA7\u8FB9\u680F\u201C\u5DF2\u7F6E\u9876\u201D\u6807\u9898\u53EF\u70B9\u51FB\u6298\u53E0/\u5C55\u5F00\u5176\u4EFB\u52A1\u5217\u8868\uFF08\u4E0E\u201C\u9879\u76EE\u201D\u201C\u5206\u7EC4\u201D\u5206\u533A\u4E00\u81F4\uFF09\uFF0C\u72B6\u6001\u8BB0\u4F4F\u3002",
|
|
260
|
+
featureSandboxReclaim: "\u63D2\u4EF6\u754C\u9762\u6C99\u7BB1\u56DE\u6536",
|
|
261
|
+
featureSandboxReclaimDesc: "\u63D2\u4EF6\u5361\u7247\u6C99\u7BB1\u6570\u91CF\u8FBE\u5230\u4E0A\u9650\u65F6\u81EA\u52A8\u91CA\u653E\u6700\u65E9\u521B\u5EFA\u7684\uFF08\u6B63\u5728\u67E5\u770B\u7684\u6392\u6700\u540E\uFF09\uFF0C\u907F\u514D 64 \u4E2A\u540D\u989D\u8017\u5C3D\u540E\u65B0\u5361\u7247\u6253\u4E0D\u5F00\uFF1B\u88AB\u91CA\u653E\u7684\u65E7\u5361\u7247\u91CD\u65B0\u6253\u5F00\u6240\u5728\u4F1A\u8BDD\u5373\u6062\u590D\uFF08\u9884\u7B97\u53EF\u5728\u914D\u7F6E\u6587\u4EF6 sandboxReclaimBudget \u8C03\u6574\uFF09\u3002",
|
|
262
|
+
featurePluginCardRetry: "\u63D2\u4EF6\u5361\u7247\u81EA\u52A8\u91CD\u8BD5",
|
|
263
|
+
featurePluginCardRetryDesc: "\u56E0\u540D\u989D\u4E0A\u9650\u52A0\u8F7D\u5931\u8D25\u7684\u63D2\u4EF6\u5361\u7247\u81EA\u52A8\u70B9\u51FB\u201C\u91CD\u65B0\u52A0\u8F7D\u201D\uFF0C\u540D\u989D\u7A7A\u51FA\u540E\u81EA\u52A8\u6062\u590D\uFF0C\u65E0\u9700\u624B\u52A8\u8E72\u5B88\u3002",
|
|
264
|
+
visionCardUi: "\u601D\u8003\u8FC7\u7A0B\u663E\u793A\u8BC6\u56FE\u5361\u7247",
|
|
238
265
|
pinnedToggleAria: "\u6298\u53E0/\u5C55\u5F00\u5DF2\u7F6E\u9876",
|
|
239
266
|
sidebarProjectSpacingName: "\u9879\u76EE\u95F4\u8DDD",
|
|
240
267
|
sidebarProjectSpacingDesc: "\u4FA7\u8FB9\u680F\u4E2D\u76F8\u90BB\u9879\u76EE\u884C\u4E4B\u95F4\u7684\u89C6\u89C9\u95F4\u8DDD\uFF08\u542B\u884C\u5185\u7559\u767D\uFF09\uFF1B\u8BBE\u7F6E\u540E\u5404\u5206\u533A\uFF08\u5DF2\u7F6E\u9876/\u9879\u76EE/\u4EFB\u52A1\uFF09\u4E4B\u95F4\u7684\u95F4\u8DDD\u4E5F\u7EDF\u4E00\u4E3A\u8BE5\u503C\u3002",
|
|
@@ -259,6 +286,33 @@
|
|
|
259
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",
|
|
260
287
|
ntpDescSuffix: "\u63D2\u4EF6\u9762\u677F",
|
|
261
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
|
+
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",
|
|
290
|
+
tabStylesPane: "\u6837\u5F0F\u8C03\u6574",
|
|
291
|
+
tabStatusPane: "\u72B6\u6001\u680F",
|
|
292
|
+
sbItemCtx: "\u4E0A\u4E0B\u6587\u5360\u7528",
|
|
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",
|
|
296
|
+
sbGroupSession: "\u4F1A\u8BDD\u7EDF\u8BA1\uFF08\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\uFF09",
|
|
297
|
+
sbGroupGlobal: "\u603B\u7EDF\u8BA1",
|
|
298
|
+
sbGroupTurn: "\u6BCF\u8F6E\u7EDF\u8BA1\uFF08\u56DE\u7B54\u672B\u5C3E\uFF09",
|
|
299
|
+
sbLabelIn: "\u8F93\u5165",
|
|
300
|
+
sbLabelOut: "\u8F93\u51FA",
|
|
301
|
+
sbLabelCache: "\u7F13\u5B58",
|
|
302
|
+
turnUsageTitle: "\u672C\u8F6E token",
|
|
303
|
+
sbLabelQuestions: "\u63D0\u95EE",
|
|
304
|
+
sbItemTodayTokens: "\u4ECA\u65E5 token",
|
|
305
|
+
sbItemTasks: "\u4EFB\u52A1\u603B\u6570",
|
|
306
|
+
sbLabelCtx: "\u4E0A\u4E0B\u6587",
|
|
307
|
+
sbLabelTurns: "\u8C03\u7528",
|
|
308
|
+
sbLabelToday: "\u4ECA\u65E5",
|
|
309
|
+
sbLabelTasks: "\u4EFB\u52A1",
|
|
310
|
+
sbItemTotalTokens: "\u7D2F\u8BA1 token",
|
|
311
|
+
sbLabelTotal: "\u7D2F\u8BA1",
|
|
312
|
+
sbMoveUp: "\u4E0A\u79FB",
|
|
313
|
+
sbMoveDown: "\u4E0B\u79FB",
|
|
314
|
+
sbVisible: "\u663E\u793A",
|
|
315
|
+
sbHidden: "\u9690\u85CF",
|
|
262
316
|
tabShortcuts: "\u5FEB\u6377\u952E",
|
|
263
317
|
hkTitle: "\u4F1A\u8BDD\u5FEB\u6377\u5207\u6362",
|
|
264
318
|
hkAltZ: "\u5728\u5F53\u524D\u4E0E\u4E0A\u6B21\u4F7F\u7528\u7684\u4F1A\u8BDD\u95F4\u6765\u56DE\u5207\u6362",
|
|
@@ -659,6 +713,11 @@
|
|
|
659
713
|
tbPluginStore: "Plugin store",
|
|
660
714
|
featurePinnedCollapse: "Collapsible Pinned section",
|
|
661
715
|
featurePinnedCollapseDesc: 'The sidebar "Pinned" header collapses/expands its task list (like Projects and Groups); the state is remembered.',
|
|
716
|
+
featureSandboxReclaim: "Plugin card sandbox reclaim",
|
|
717
|
+
featureSandboxReclaimDesc: "Releases the oldest plugin-card sandboxes once the cap is hit (the one being viewed goes last), so new cards keep opening after the 64-slot pool fills up; released cards come back when their session is reopened (budget adjustable via sandboxReclaimBudget in the config file).",
|
|
718
|
+
featurePluginCardRetry: "Plugin card auto-retry",
|
|
719
|
+
featurePluginCardRetryDesc: 'Auto-clicks "Reload" on cards that failed the slot cap; they recover as soon as a slot frees up.',
|
|
720
|
+
visionCardUi: "Vision cards",
|
|
662
721
|
pinnedToggleAria: "Collapse/expand Pinned",
|
|
663
722
|
sidebarProjectSpacingName: "Project spacing",
|
|
664
723
|
sidebarProjectSpacingDesc: "Visual spacing between adjacent project rows in the sidebar (row padding included); when set, section gaps (Pinned/Projects/Tasks) follow the same value.",
|
|
@@ -683,6 +742,33 @@
|
|
|
683
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.',
|
|
684
743
|
ntpDescSuffix: "plugin panel",
|
|
685
744
|
ntpNeedSession: "Open a task session first, then open plugin panels from the new tab page",
|
|
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".',
|
|
746
|
+
tabStylesPane: "Styles",
|
|
747
|
+
tabStatusPane: "Status bar",
|
|
748
|
+
sbItemCtx: "Context usage",
|
|
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
|
+
sbGroupSession: "Session statistics (follows current session)",
|
|
753
|
+
sbGroupGlobal: "Global statistics",
|
|
754
|
+
sbGroupTurn: "Per-turn statistics (answer rows)",
|
|
755
|
+
sbLabelIn: "in",
|
|
756
|
+
sbLabelOut: "out",
|
|
757
|
+
sbLabelCache: "cache",
|
|
758
|
+
turnUsageTitle: "Turn tokens",
|
|
759
|
+
sbLabelQuestions: "asks",
|
|
760
|
+
sbItemTodayTokens: "Today tokens",
|
|
761
|
+
sbItemTasks: "Tasks",
|
|
762
|
+
sbLabelCtx: "ctx",
|
|
763
|
+
sbLabelTurns: "calls",
|
|
764
|
+
sbLabelToday: "today",
|
|
765
|
+
sbLabelTasks: "tasks",
|
|
766
|
+
sbItemTotalTokens: "Total tokens",
|
|
767
|
+
sbLabelTotal: "total",
|
|
768
|
+
sbMoveUp: "Up",
|
|
769
|
+
sbMoveDown: "Down",
|
|
770
|
+
sbVisible: "shown",
|
|
771
|
+
sbHidden: "hidden",
|
|
686
772
|
tabShortcuts: "Shortcuts",
|
|
687
773
|
hkTitle: "Session quick switch",
|
|
688
774
|
hkAltZ: "Toggle between the current and the last-used session",
|
|
@@ -1022,20 +1108,20 @@
|
|
|
1022
1108
|
}
|
|
1023
1109
|
}
|
|
1024
1110
|
function observeRadixPopups(onPopup) {
|
|
1025
|
-
const
|
|
1111
|
+
const seen2 = /* @__PURE__ */ new WeakSet();
|
|
1026
1112
|
const check = (node) => {
|
|
1027
1113
|
if (!(node instanceof HTMLElement)) return;
|
|
1028
1114
|
if (node.hasAttribute("data-radix-popper-content-wrapper")) {
|
|
1029
1115
|
requestAnimationFrame(() => {
|
|
1030
1116
|
const content = node.firstElementChild;
|
|
1031
|
-
if (content && !
|
|
1032
|
-
|
|
1117
|
+
if (content && !seen2.has(content)) {
|
|
1118
|
+
seen2.add(content);
|
|
1033
1119
|
onPopup(content);
|
|
1034
1120
|
}
|
|
1035
1121
|
});
|
|
1036
1122
|
}
|
|
1037
|
-
if (node.getAttribute && node.getAttribute("role") === "menu" && !
|
|
1038
|
-
|
|
1123
|
+
if (node.getAttribute && node.getAttribute("role") === "menu" && !seen2.has(node)) {
|
|
1124
|
+
seen2.add(node);
|
|
1039
1125
|
requestAnimationFrame(() => {
|
|
1040
1126
|
if (node.isConnected) onPopup(node);
|
|
1041
1127
|
});
|
|
@@ -1695,6 +1781,56 @@
|
|
|
1695
1781
|
text-align: center;
|
|
1696
1782
|
color: var(--color-muted-foreground, #888);
|
|
1697
1783
|
}
|
|
1784
|
+
/* \u72B6\u6001\u680F\u7EDF\u8BA1\uFF08status-bar.js\uFF09\uFF1A\u8F93\u5165\u6846\u4E0B\u65B9\u53F3\u5BF9\u9F50\u7684\u4E00\u884C\u5C0F\u5B57\uFF0C\u6BCF\u9879\u5E26 lucide \u5C0F\u56FE\u6807\u3002
|
|
1785
|
+
\u4E0A\u4E0B\u95F4\u8DDD\u7531\u811A\u672C\u6309\u89C6\u56FE\u63A7\u5236\uFF08status-bar.js\uFF1A\u4E0B\u65B9\u6709\u5185\u5BB9\u65F6\u5BF9\u79F0 7px\uFF0C
|
|
1786
|
+
\u4E0B\u65B9\u662F\u7A97\u5E95\u7559\u767D\u65F6\u8D1F margin \u538B\u5165\u8D34\u5E95\uFF09 */
|
|
1787
|
+
.zcodepro-statusbar {
|
|
1788
|
+
display: flex;
|
|
1789
|
+
justify-content: flex-end;
|
|
1790
|
+
align-items: center;
|
|
1791
|
+
gap: 8px;
|
|
1792
|
+
padding: 7px 14px 0;
|
|
1793
|
+
font-size: 11px;
|
|
1794
|
+
line-height: 1.4;
|
|
1795
|
+
color: var(--color-muted-foreground, #888);
|
|
1796
|
+
user-select: none;
|
|
1797
|
+
pointer-events: none;
|
|
1798
|
+
}
|
|
1799
|
+
.zcodepro-statusbar span[data-tone='warn'] { color: var(--color-amber-500, #f59e0b); }
|
|
1800
|
+
.zcodepro-statusbar span[data-tone='danger'] { color: var(--color-red-500, #ef4444); }
|
|
1801
|
+
.zcodepro-statusbar-sep { opacity: 0.45; }
|
|
1802
|
+
/* \u4F1A\u8BDD\u7EC4\u4E0E\u5168\u5C40\u7EC4\u4E4B\u95F4\u7684\u5206\u754C\u7AD6\u7EBF */
|
|
1803
|
+
.zcodepro-statusbar-groupsep {
|
|
1804
|
+
width: 1px;
|
|
1805
|
+
height: 10px;
|
|
1806
|
+
background: currentColor;
|
|
1807
|
+
opacity: 0.3;
|
|
1808
|
+
margin: 0 2px;
|
|
1809
|
+
}
|
|
1810
|
+
/* \u6BCF\u9879\u5185\u90E8\u7528 flex \u5BF9\u9F50\uFF1A\u56FE\u6807\u3001\u6807\u7B7E\u3001\u6570\u503C\u5782\u76F4\u5C45\u4E2D\uFF0C\u95F4\u8DDD\u7EDF\u4E00 */
|
|
1811
|
+
.zcodepro-statusbar span[title] {
|
|
1812
|
+
display: inline-flex;
|
|
1813
|
+
align-items: center;
|
|
1814
|
+
gap: 3px;
|
|
1815
|
+
white-space: nowrap;
|
|
1816
|
+
}
|
|
1817
|
+
.zcodepro-sb-icon {
|
|
1818
|
+
width: 12px;
|
|
1819
|
+
height: 12px;
|
|
1820
|
+
flex-shrink: 0;
|
|
1821
|
+
opacity: 0.6;
|
|
1822
|
+
}
|
|
1823
|
+
.zcodepro-statusbar b { font-weight: 600; color: var(--color-foreground-subtle, #666); }
|
|
1824
|
+
.zcodepro-statusbar i {
|
|
1825
|
+
font-style: normal;
|
|
1826
|
+
opacity: 0.7;
|
|
1827
|
+
font-size: 10px;
|
|
1828
|
+
}
|
|
1829
|
+
/* \u9879\u5185\u77ED\u6807\u7B7E\uFF08\u5982\u201C\u4E0A\u4E0B\u6587\u201D\u201C\u7D2F\u8BA1\u201D\uFF09\uFF0C\u5F31\u5316\u4E0D\u62A2\u6570\u503C */
|
|
1830
|
+
.zcodepro-statusbar em {
|
|
1831
|
+
font-style: normal;
|
|
1832
|
+
opacity: 0.75;
|
|
1833
|
+
}
|
|
1698
1834
|
.zcodepro-switcher-ws {
|
|
1699
1835
|
font-size: 11px;
|
|
1700
1836
|
color: var(--color-muted-foreground, #888);
|
|
@@ -2504,10 +2640,10 @@
|
|
|
2504
2640
|
}
|
|
2505
2641
|
function handleProjectMenu(content) {
|
|
2506
2642
|
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2507
|
-
const
|
|
2643
|
+
const items2 = itemsOf(content);
|
|
2508
2644
|
const newUi = isNewProjectSidebar();
|
|
2509
2645
|
const menuRow = newUi ? openMenuProjectRow() : null;
|
|
2510
|
-
const anchor = newUi ?
|
|
2646
|
+
const anchor = newUi ? items2.find((el) => el.getAttribute("data-testid") === "virtual-project-edit") : items2.find(
|
|
2511
2647
|
(el) => el.hasAttribute("data-testid") && REMOVE_TEXTS.some((x) => itemText(el).startsWith(x))
|
|
2512
2648
|
);
|
|
2513
2649
|
if (!anchor) return;
|
|
@@ -2600,7 +2736,7 @@
|
|
|
2600
2736
|
if (looksLikePath(p2)) return p2;
|
|
2601
2737
|
return pathFromReactFiber(content);
|
|
2602
2738
|
}
|
|
2603
|
-
function appendMenuItem(content, template, anchor, { marker, label, icon, onPick }) {
|
|
2739
|
+
function appendMenuItem(content, template, anchor, { marker, label, icon: icon2, onPick }) {
|
|
2604
2740
|
const item = template.cloneNode(true);
|
|
2605
2741
|
item.removeAttribute("data-testid");
|
|
2606
2742
|
item.removeAttribute("data-highlighted");
|
|
@@ -2609,7 +2745,7 @@
|
|
|
2609
2745
|
item.setAttribute("data-zcodepro-item", marker);
|
|
2610
2746
|
for (const child of [...item.childNodes]) child.remove();
|
|
2611
2747
|
const origIcon = template.querySelector("svg");
|
|
2612
|
-
item.append(buildIcon(origIcon?.getAttribute("class") || "size-4",
|
|
2748
|
+
item.append(buildIcon(origIcon?.getAttribute("class") || "size-4", icon2), document.createTextNode(label));
|
|
2613
2749
|
item.addEventListener("mouseenter", () => {
|
|
2614
2750
|
for (const el of content.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
2615
2751
|
item.setAttribute("data-highlighted", "");
|
|
@@ -2624,8 +2760,8 @@
|
|
|
2624
2760
|
}
|
|
2625
2761
|
function handleFileMenu(content) {
|
|
2626
2762
|
if (content.dataset.zcodeproFileMenu) return;
|
|
2627
|
-
const
|
|
2628
|
-
const copyAbs =
|
|
2763
|
+
const items2 = itemsOf(content);
|
|
2764
|
+
const copyAbs = items2.find((el) => COPY_ABS_TEXTS.some((x) => itemText(el).startsWith(x)));
|
|
2629
2765
|
if (!copyAbs) return;
|
|
2630
2766
|
content.dataset.zcodeproFileMenu = "1";
|
|
2631
2767
|
void (async () => {
|
|
@@ -2640,7 +2776,7 @@
|
|
|
2640
2776
|
}).catch(() => {
|
|
2641
2777
|
});
|
|
2642
2778
|
};
|
|
2643
|
-
const noApps =
|
|
2779
|
+
const noApps = items2.find((el) => NO_APPS_TEXTS.some((x) => itemText(el) === x)) || content.querySelector('[data-disabled][role="menuitem"]');
|
|
2644
2780
|
const openAnchor = noApps && content.contains(noApps) ? noApps : copyAbs;
|
|
2645
2781
|
appendMenuItem(content, copyAbs, openAnchor, {
|
|
2646
2782
|
marker: "file-open-default",
|
|
@@ -2850,10 +2986,10 @@
|
|
|
2850
2986
|
function startImageMenu() {
|
|
2851
2987
|
if (typeof window === "undefined") return;
|
|
2852
2988
|
if (typeof navigator.clipboard?.write !== "function" || typeof window.ClipboardItem === "undefined") return;
|
|
2853
|
-
let
|
|
2989
|
+
let enabled9 = true;
|
|
2854
2990
|
const refresh = () => {
|
|
2855
2991
|
void getConfig().then((c) => {
|
|
2856
|
-
|
|
2992
|
+
enabled9 = !(c.features && c.features.imageCopy === false);
|
|
2857
2993
|
});
|
|
2858
2994
|
};
|
|
2859
2995
|
refresh();
|
|
@@ -2862,7 +2998,7 @@
|
|
|
2862
2998
|
const img = copyTargetOf(e.target, e.clientX, e.clientY);
|
|
2863
2999
|
if (!img) return;
|
|
2864
3000
|
e.preventDefault();
|
|
2865
|
-
if (
|
|
3001
|
+
if (enabled9) showMenu(e.clientX, e.clientY, img);
|
|
2866
3002
|
refresh();
|
|
2867
3003
|
}, true);
|
|
2868
3004
|
}
|
|
@@ -2966,7 +3102,7 @@
|
|
|
2966
3102
|
function waitFor(getter, timeoutMs, step) {
|
|
2967
3103
|
const start = Date.now();
|
|
2968
3104
|
return new Promise((resolve, reject) => {
|
|
2969
|
-
const
|
|
3105
|
+
const tick6 = () => {
|
|
2970
3106
|
let v = null;
|
|
2971
3107
|
try {
|
|
2972
3108
|
v = getter();
|
|
@@ -2980,9 +3116,9 @@
|
|
|
2980
3116
|
reject(new Error(step));
|
|
2981
3117
|
return;
|
|
2982
3118
|
}
|
|
2983
|
-
setTimeout(
|
|
3119
|
+
setTimeout(tick6, 120);
|
|
2984
3120
|
};
|
|
2985
|
-
|
|
3121
|
+
tick6();
|
|
2986
3122
|
});
|
|
2987
3123
|
}
|
|
2988
3124
|
function setReactInputValue(input, value) {
|
|
@@ -3754,7 +3890,7 @@
|
|
|
3754
3890
|
setState(L.upgradeFound.replaceAll("{v}", res.latest || ""));
|
|
3755
3891
|
btn.textContent = L.upgradeNow;
|
|
3756
3892
|
};
|
|
3757
|
-
const
|
|
3893
|
+
const tick6 = async () => {
|
|
3758
3894
|
const res = await rpc(endpoint + "/upgrade");
|
|
3759
3895
|
if (!res.ok) {
|
|
3760
3896
|
stopPoll();
|
|
@@ -3794,9 +3930,9 @@
|
|
|
3794
3930
|
btn.textContent = L.upgradeStop;
|
|
3795
3931
|
setState(L.upgradeRunning);
|
|
3796
3932
|
timer = setInterval(() => {
|
|
3797
|
-
void
|
|
3933
|
+
void tick6();
|
|
3798
3934
|
}, 1500);
|
|
3799
|
-
void
|
|
3935
|
+
void tick6();
|
|
3800
3936
|
};
|
|
3801
3937
|
void (async () => {
|
|
3802
3938
|
const res = await rpc(endpoint + "/upgrade");
|
|
@@ -4005,6 +4141,16 @@
|
|
|
4005
4141
|
if (await setFeature("imageCopy", next)) f.imageCopy = next;
|
|
4006
4142
|
refreshRows();
|
|
4007
4143
|
}),
|
|
4144
|
+
settingRow(L.featureSandboxReclaim, L.featureSandboxReclaimDesc, f.sandboxReclaim !== false, async () => {
|
|
4145
|
+
const next = !(f.sandboxReclaim !== false);
|
|
4146
|
+
if (await setFeature("sandboxReclaim", next)) f.sandboxReclaim = next;
|
|
4147
|
+
refreshRows();
|
|
4148
|
+
}),
|
|
4149
|
+
settingRow(L.featurePluginCardRetry, L.featurePluginCardRetryDesc, f.pluginCardRetry !== false, async () => {
|
|
4150
|
+
const next = !(f.pluginCardRetry !== false);
|
|
4151
|
+
if (await setFeature("pluginCardRetry", next)) f.pluginCardRetry = next;
|
|
4152
|
+
refreshRows();
|
|
4153
|
+
}),
|
|
4008
4154
|
settingRow(L.featureWsRunning, L.featureWsRunningDesc, f.wsRunningSpin !== false, async () => {
|
|
4009
4155
|
const next = !(f.wsRunningSpin !== false);
|
|
4010
4156
|
if (await setFeature("wsRunningSpin", next)) f.wsRunningSpin = next;
|
|
@@ -4047,7 +4193,7 @@
|
|
|
4047
4193
|
const WECHAT_ID = "ai4only";
|
|
4048
4194
|
const ns = "http://www.w3.org/2000/svg";
|
|
4049
4195
|
const extIcon = () => {
|
|
4050
|
-
const
|
|
4196
|
+
const icon2 = h("svg", {
|
|
4051
4197
|
viewBox: "0 0 24 24",
|
|
4052
4198
|
fill: "none",
|
|
4053
4199
|
stroke: "currentColor",
|
|
@@ -4059,11 +4205,11 @@
|
|
|
4059
4205
|
for (const d of ["M15 3h6v6", "M10 14 21 3", "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"]) {
|
|
4060
4206
|
const p2 = document.createElementNS(ns, "path");
|
|
4061
4207
|
p2.setAttribute("d", d);
|
|
4062
|
-
|
|
4208
|
+
icon2.append(p2);
|
|
4063
4209
|
}
|
|
4064
|
-
return
|
|
4210
|
+
return icon2;
|
|
4065
4211
|
};
|
|
4066
|
-
const communityCard = (title, desc,
|
|
4212
|
+
const communityCard = (title, desc, icon2, onClick) => h(
|
|
4067
4213
|
"div",
|
|
4068
4214
|
{
|
|
4069
4215
|
class: "flex cursor-pointer items-center justify-between gap-2 rounded-xl border border-border p-2 transition-colors hover:bg-surface-hover",
|
|
@@ -4075,7 +4221,7 @@
|
|
|
4075
4221
|
h("div", { class: "truncate text-ui-sm font-medium text-foreground" }, title),
|
|
4076
4222
|
h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" }, desc)
|
|
4077
4223
|
),
|
|
4078
|
-
|
|
4224
|
+
icon2()
|
|
4079
4225
|
);
|
|
4080
4226
|
const communityCards = h(
|
|
4081
4227
|
"div",
|
|
@@ -4218,7 +4364,7 @@
|
|
|
4218
4364
|
),
|
|
4219
4365
|
hkCard
|
|
4220
4366
|
);
|
|
4221
|
-
const paneStyles = h("div", { role: "tabpanel", class: "mt-
|
|
4367
|
+
const paneStyles = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
4222
4368
|
const panePerf = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4223
4369
|
const paneAgents = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
4224
4370
|
const paneProxy = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
@@ -4433,7 +4579,184 @@
|
|
|
4433
4579
|
for (const c of fontCells) c.setOptions(list);
|
|
4434
4580
|
})();
|
|
4435
4581
|
renderToolbarSwitch();
|
|
4436
|
-
|
|
4582
|
+
const paneStylesSub1 = h("div", { class: "mt-4" });
|
|
4583
|
+
const paneStylesSub2 = h("div", { class: "mt-4", style: "display:none" });
|
|
4584
|
+
const ITEM_NAMES = {
|
|
4585
|
+
ctx: "sbItemCtx",
|
|
4586
|
+
questions: "sbItemQuestions",
|
|
4587
|
+
todayTokens: "sbItemTodayTokens",
|
|
4588
|
+
totalTokens: "sbItemTotalTokens",
|
|
4589
|
+
tasks: "sbItemTasks"
|
|
4590
|
+
};
|
|
4591
|
+
const sbItems = () => {
|
|
4592
|
+
const saved = config.statusBar && Array.isArray(config.statusBar.items) ? config.statusBar.items : null;
|
|
4593
|
+
if (!saved) return DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
4594
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
4595
|
+
const list = saved.filter((x) => ITEM_NAMES[x.id]).map((x) => ({ on: x.on !== false, id: x.id }));
|
|
4596
|
+
for (const d of DEFAULT_STATUS_ITEMS) if (!byId.has(d.id)) list.push({ ...d });
|
|
4597
|
+
return [
|
|
4598
|
+
...list.filter((x) => STATUS_SESSION_IDS.has(x.id)),
|
|
4599
|
+
...list.filter((x) => STATUS_GLOBAL_IDS.has(x.id))
|
|
4600
|
+
];
|
|
4601
|
+
};
|
|
4602
|
+
let sbSaving = false;
|
|
4603
|
+
const saveSbItems = async (next) => {
|
|
4604
|
+
if (sbSaving) return;
|
|
4605
|
+
sbSaving = true;
|
|
4606
|
+
try {
|
|
4607
|
+
const res = await rpc("/config", { method: "POST", body: { statusBar: { items: next } } });
|
|
4608
|
+
clearConfigCache();
|
|
4609
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4610
|
+
if (!res.ok) {
|
|
4611
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4612
|
+
renderSbItems();
|
|
4613
|
+
return;
|
|
4614
|
+
}
|
|
4615
|
+
if (res.config && res.config.statusBar) config.statusBar = res.config.statusBar;
|
|
4616
|
+
} finally {
|
|
4617
|
+
sbSaving = false;
|
|
4618
|
+
}
|
|
4619
|
+
renderSbItems();
|
|
4620
|
+
};
|
|
4621
|
+
const sbList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4622
|
+
const sbGlobalList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4623
|
+
const TURN_NAMES = { turnIn: "sbLabelIn", turnOut: "sbLabelOut", turnCache: "sbLabelCache" };
|
|
4624
|
+
const turnItems = () => {
|
|
4625
|
+
const saved = config.statusBar && Array.isArray(config.statusBar.turnItems) ? config.statusBar.turnItems : null;
|
|
4626
|
+
if (!saved) return DEFAULT_TURN_ITEMS.map((x) => ({ ...x }));
|
|
4627
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
4628
|
+
const list = saved.filter((x) => TURN_NAMES[x.id]).map((x) => ({ on: x.on !== false, id: x.id }));
|
|
4629
|
+
for (const d of DEFAULT_TURN_ITEMS) if (!byId.has(d.id)) list.push({ ...d });
|
|
4630
|
+
return list;
|
|
4631
|
+
};
|
|
4632
|
+
const saveTurnItems = async (next) => {
|
|
4633
|
+
if (sbSaving) return;
|
|
4634
|
+
sbSaving = true;
|
|
4635
|
+
try {
|
|
4636
|
+
const res = await rpc("/config", { method: "POST", body: { statusBar: { turnItems: next } } });
|
|
4637
|
+
clearConfigCache();
|
|
4638
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4639
|
+
if (!res.ok) {
|
|
4640
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4641
|
+
renderSbItems();
|
|
4642
|
+
return;
|
|
4643
|
+
}
|
|
4644
|
+
if (res.config && res.config.statusBar) config.statusBar = res.config.statusBar;
|
|
4645
|
+
} finally {
|
|
4646
|
+
sbSaving = false;
|
|
4647
|
+
}
|
|
4648
|
+
renderSbItems();
|
|
4649
|
+
};
|
|
4650
|
+
const turnList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4651
|
+
const renderSbItems = () => {
|
|
4652
|
+
turnList.replaceChildren(...turnItems().map((it, i) => h(
|
|
4653
|
+
"div",
|
|
4654
|
+
{ class: "flex items-center gap-2 px-3 py-2" },
|
|
4655
|
+
h("span", { class: "min-w-0 flex-1 truncate text-ui-sm text-foreground-subtle" }, L[TURN_NAMES[it.id]] || it.id),
|
|
4656
|
+
btnSmall(it.on ? L.sbVisible : L.sbHidden, () => {
|
|
4657
|
+
void saveTurnItems(turnItems().map((x) => x.id === it.id ? { ...x, on: !x.on } : x));
|
|
4658
|
+
}),
|
|
4659
|
+
btnSmall("\u2191", () => {
|
|
4660
|
+
const a = turnItems();
|
|
4661
|
+
if (i > 0) {
|
|
4662
|
+
[a[i - 1], a[i]] = [a[i], a[i - 1]];
|
|
4663
|
+
void saveTurnItems(a);
|
|
4664
|
+
}
|
|
4665
|
+
}),
|
|
4666
|
+
btnSmall("\u2193", () => {
|
|
4667
|
+
const a = turnItems();
|
|
4668
|
+
if (i < a.length - 1) {
|
|
4669
|
+
[a[i], a[i + 1]] = [a[i + 1], a[i]];
|
|
4670
|
+
void saveTurnItems(a);
|
|
4671
|
+
}
|
|
4672
|
+
})
|
|
4673
|
+
)));
|
|
4674
|
+
const list = sbItems();
|
|
4675
|
+
const renderGroup = (el, groupIds) => {
|
|
4676
|
+
const idxs = list.map((x, i) => i).filter((i) => groupIds.has(list[i].id));
|
|
4677
|
+
el.replaceChildren(...idxs.map((i) => {
|
|
4678
|
+
const it = list[i];
|
|
4679
|
+
const swap = (dir) => {
|
|
4680
|
+
const a = sbItems();
|
|
4681
|
+
const same = a.map((x, j) => j).filter((j) => groupIds.has(a[j].id));
|
|
4682
|
+
const pos = same.indexOf(i);
|
|
4683
|
+
const other = same[pos + dir];
|
|
4684
|
+
if (other == null) return;
|
|
4685
|
+
[a[i], a[other]] = [a[other], a[i]];
|
|
4686
|
+
void saveSbItems(a);
|
|
4687
|
+
};
|
|
4688
|
+
return h(
|
|
4689
|
+
"div",
|
|
4690
|
+
{ class: "flex items-center gap-2 px-3 py-2" },
|
|
4691
|
+
h(
|
|
4692
|
+
"span",
|
|
4693
|
+
{ class: "min-w-0 flex-1 truncate text-ui-sm text-foreground-subtle" },
|
|
4694
|
+
L[ITEM_NAMES[it.id]] || it.id
|
|
4695
|
+
),
|
|
4696
|
+
btnSmall(it.on ? L.sbVisible : L.sbHidden, () => {
|
|
4697
|
+
void saveSbItems(sbItems().map((x, j) => j === i ? { ...x, on: !x.on } : x));
|
|
4698
|
+
}),
|
|
4699
|
+
btnSmall("\u2191", () => swap(-1)),
|
|
4700
|
+
btnSmall("\u2193", () => swap(1))
|
|
4701
|
+
);
|
|
4702
|
+
}));
|
|
4703
|
+
};
|
|
4704
|
+
renderGroup(sbList, STATUS_SESSION_IDS);
|
|
4705
|
+
renderGroup(sbGlobalList, STATUS_GLOBAL_IDS);
|
|
4706
|
+
};
|
|
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();
|
|
4729
|
+
paneStylesSub2.append(
|
|
4730
|
+
masterRow,
|
|
4731
|
+
h("p", { class: "mt-2 text-ui-sm/relaxed text-foreground-subtle" }, L.featureStatusBarDesc),
|
|
4732
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupSession),
|
|
4733
|
+
sbList,
|
|
4734
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupGlobal),
|
|
4735
|
+
sbGlobalList,
|
|
4736
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupTurn),
|
|
4737
|
+
turnList
|
|
4738
|
+
);
|
|
4739
|
+
let stylesSubTab = "styles";
|
|
4740
|
+
const stylesSubTablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist" });
|
|
4741
|
+
const renderStylesSubTabs = () => stylesSubTablist.replaceChildren(...[
|
|
4742
|
+
["styles", L.tabStylesPane],
|
|
4743
|
+
["status", L.tabStatusPane]
|
|
4744
|
+
].map(([id, label]) => h("button", {
|
|
4745
|
+
type: "button",
|
|
4746
|
+
role: "tab",
|
|
4747
|
+
class: "zcodepro-tab",
|
|
4748
|
+
"aria-selected": String(stylesSubTab === id),
|
|
4749
|
+
"data-state": stylesSubTab === id ? "active" : "inactive",
|
|
4750
|
+
onClick: () => {
|
|
4751
|
+
stylesSubTab = id;
|
|
4752
|
+
paneStylesSub1.style.display = id === "styles" ? "" : "none";
|
|
4753
|
+
paneStylesSub2.style.display = id === "status" ? "" : "none";
|
|
4754
|
+
renderStylesSubTabs();
|
|
4755
|
+
}
|
|
4756
|
+
}, label)));
|
|
4757
|
+
renderStylesSubTabs();
|
|
4758
|
+
paneStyles.append(stylesSubTablist, paneStylesSub1, paneStylesSub2);
|
|
4759
|
+
paneStylesSub1.append(
|
|
4437
4760
|
toolbarSwitchWrap,
|
|
4438
4761
|
h(
|
|
4439
4762
|
"div",
|
|
@@ -5431,6 +5754,11 @@
|
|
|
5431
5754
|
h(
|
|
5432
5755
|
"div",
|
|
5433
5756
|
{ class: "ml-auto flex items-center gap-4" },
|
|
5757
|
+
settingRow(L.visionCardUi, "", visionCfg.cardUi !== false, async () => {
|
|
5758
|
+
visionCfg.cardUi = !(visionCfg.cardUi !== false);
|
|
5759
|
+
await persistVision();
|
|
5760
|
+
renderVision();
|
|
5761
|
+
}),
|
|
5434
5762
|
settingRow(L.visionForceIntercept, "", visionCfg.forceIntercept !== false, async () => {
|
|
5435
5763
|
visionCfg.forceIntercept = !(visionCfg.forceIntercept !== false);
|
|
5436
5764
|
await persistVision();
|
|
@@ -6506,11 +6834,11 @@
|
|
|
6506
6834
|
const rootEl = document.getElementById("root");
|
|
6507
6835
|
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6508
6836
|
if (!containerKey) return null;
|
|
6509
|
-
const
|
|
6837
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
6510
6838
|
let found = null;
|
|
6511
6839
|
const scanObj = (o) => {
|
|
6512
|
-
if (!o || typeof o !== "object" ||
|
|
6513
|
-
|
|
6840
|
+
if (!o || typeof o !== "object" || seen2.has(o) || found) return;
|
|
6841
|
+
seen2.add(o);
|
|
6514
6842
|
const ts = o.zcodeTaskService;
|
|
6515
6843
|
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6516
6844
|
};
|
|
@@ -6649,22 +6977,22 @@
|
|
|
6649
6977
|
}, 0);
|
|
6650
6978
|
}
|
|
6651
6979
|
function apply() {
|
|
6652
|
-
const
|
|
6980
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
6653
6981
|
for (const row of document.querySelectorAll(WS_SEL())) {
|
|
6654
6982
|
const path = rowPath(row);
|
|
6655
6983
|
if (!path) continue;
|
|
6656
|
-
|
|
6984
|
+
seen2.add(path);
|
|
6657
6985
|
const head = wsHead(row);
|
|
6658
6986
|
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6659
6987
|
const domRunning = !!(runningByWs.get(path) && runningByWs.get(path).size);
|
|
6660
6988
|
const normP = (v) => String(v || "").replace(/[\\/]+$/, "");
|
|
6661
6989
|
const running = enabled2 && collapsed && (activeProjectPaths.size ? [...activeProjectPaths].some((p2) => normP(p2) === normP(path)) : domRunning);
|
|
6662
|
-
const
|
|
6663
|
-
|
|
6664
|
-
setRunningIcon(
|
|
6990
|
+
const icon2 = iconHolderOf(row);
|
|
6991
|
+
icon2?.classList.toggle("zcodepro-ws-running", running);
|
|
6992
|
+
setRunningIcon(icon2, running);
|
|
6665
6993
|
}
|
|
6666
6994
|
applySectionSpin();
|
|
6667
|
-
for (const ws of [...runningByWs.keys()]) if (!
|
|
6995
|
+
for (const ws of [...runningByWs.keys()]) if (!seen2.has(ws)) runningByWs.delete(ws);
|
|
6668
6996
|
}
|
|
6669
6997
|
var headInfoCache = /* @__PURE__ */ new WeakMap();
|
|
6670
6998
|
var PROJECT_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u9879\u76EE", "projects"]);
|
|
@@ -7466,20 +7794,20 @@
|
|
|
7466
7794
|
}
|
|
7467
7795
|
function findBridge() {
|
|
7468
7796
|
let holder = null;
|
|
7469
|
-
const
|
|
7470
|
-
const
|
|
7471
|
-
if (!o || typeof o !== "object" ||
|
|
7472
|
-
|
|
7797
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
7798
|
+
const scan5 = (o) => {
|
|
7799
|
+
if (!o || typeof o !== "object" || seen2.has(o) || holder) return;
|
|
7800
|
+
seen2.add(o);
|
|
7473
7801
|
if (typeof o.pluginUiBridgeService === "object" && o.pluginUiBridgeService) {
|
|
7474
7802
|
holder = o.pluginUiBridgeService;
|
|
7475
7803
|
return;
|
|
7476
7804
|
}
|
|
7477
|
-
for (const v of Object.values(o)) if (v && typeof v === "object")
|
|
7805
|
+
for (const v of Object.values(o)) if (v && typeof v === "object") scan5(v);
|
|
7478
7806
|
};
|
|
7479
7807
|
eachFiber((f) => {
|
|
7480
7808
|
for (const h2 of [f.memoizedProps, f.memoizedState]) {
|
|
7481
7809
|
if (!h2 || typeof h2 !== "object") continue;
|
|
7482
|
-
|
|
7810
|
+
scan5(h2);
|
|
7483
7811
|
if (holder) return true;
|
|
7484
7812
|
}
|
|
7485
7813
|
return false;
|
|
@@ -7615,6 +7943,423 @@
|
|
|
7615
7943
|
setInterval(tryInject, 5e3);
|
|
7616
7944
|
}
|
|
7617
7945
|
|
|
7946
|
+
// src/inject/features/status-bar.js
|
|
7947
|
+
var enabled4 = true;
|
|
7948
|
+
var items = DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
7949
|
+
var barEl = null;
|
|
7950
|
+
var lastStats = null;
|
|
7951
|
+
function readCtx() {
|
|
7952
|
+
for (const el of document.querySelectorAll("[title], [aria-label]")) {
|
|
7953
|
+
if (el.closest(".zcodepro-statusbar")) continue;
|
|
7954
|
+
const text = el.getAttribute("title") || el.getAttribute("aria-label") || "";
|
|
7955
|
+
if (!/上下文|context/i.test(text)) continue;
|
|
7956
|
+
const m = text.match(/([\d][\d,]*)\s*\/[^0-9]*([\d][\d,]*)/);
|
|
7957
|
+
if (!m) continue;
|
|
7958
|
+
const used = Number(m[1].replace(/,/g, ""));
|
|
7959
|
+
const size = Number(m[2].replace(/,/g, ""));
|
|
7960
|
+
if (used > 0 && size > used) return { used, size };
|
|
7961
|
+
}
|
|
7962
|
+
return null;
|
|
7963
|
+
}
|
|
7964
|
+
var usageSvc = null;
|
|
7965
|
+
var official = null;
|
|
7966
|
+
var officialAt = 0;
|
|
7967
|
+
function eachFiber2(visit) {
|
|
7968
|
+
const rootEl = document.getElementById("root");
|
|
7969
|
+
const key = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
7970
|
+
if (!key) return;
|
|
7971
|
+
let visited = 0;
|
|
7972
|
+
const walk = (f) => {
|
|
7973
|
+
if (!f || visited > 2e5) return false;
|
|
7974
|
+
visited++;
|
|
7975
|
+
if (visit(f)) return true;
|
|
7976
|
+
return walk(f.child) || walk(f.sibling);
|
|
7977
|
+
};
|
|
7978
|
+
walk(rootEl[key]);
|
|
7979
|
+
}
|
|
7980
|
+
function findUsageService() {
|
|
7981
|
+
let found = null;
|
|
7982
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
7983
|
+
const scan5 = (o) => {
|
|
7984
|
+
if (!o || typeof o !== "object" || seen2.has(o) || found) return;
|
|
7985
|
+
seen2.add(o);
|
|
7986
|
+
if (typeof o.usageStatsService === "object" && o.usageStatsService) {
|
|
7987
|
+
found = o.usageStatsService;
|
|
7988
|
+
return;
|
|
7989
|
+
}
|
|
7990
|
+
for (const v of Object.values(o)) if (v && typeof v === "object") scan5(v);
|
|
7991
|
+
};
|
|
7992
|
+
eachFiber2((f) => {
|
|
7993
|
+
for (const h2 of [f.memoizedProps, f.memoizedState]) {
|
|
7994
|
+
if (!h2 || typeof h2 !== "object") continue;
|
|
7995
|
+
scan5(h2);
|
|
7996
|
+
if (found) return true;
|
|
7997
|
+
}
|
|
7998
|
+
return false;
|
|
7999
|
+
});
|
|
8000
|
+
return found;
|
|
8001
|
+
}
|
|
8002
|
+
function refreshOfficial() {
|
|
8003
|
+
const period = official ? 5 * 6e4 : 3e4;
|
|
8004
|
+
if (Date.now() - officialAt < period) return;
|
|
8005
|
+
officialAt = Date.now();
|
|
8006
|
+
void (async () => {
|
|
8007
|
+
try {
|
|
8008
|
+
if (!usageSvc) usageSvc = findUsageService();
|
|
8009
|
+
if (!usageSvc || typeof usageSvc.getAppUsageSnapshot !== "function") return;
|
|
8010
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
8011
|
+
const [all, d7] = await Promise.all([
|
|
8012
|
+
usageSvc.getAppUsageSnapshot({ range: "all", timeZone }),
|
|
8013
|
+
usageSvc.getAppUsageSnapshot({ range: "7d", timeZone })
|
|
8014
|
+
]);
|
|
8015
|
+
const now = /* @__PURE__ */ new Date();
|
|
8016
|
+
const key = now.getFullYear() + "-" + String(now.getMonth() + 1).padStart(2, "0") + "-" + String(now.getDate()).padStart(2, "0");
|
|
8017
|
+
let todayTokens = 0;
|
|
8018
|
+
const day = (d7 && Array.isArray(d7.dailyModelUsage) ? d7.dailyModelUsage : []).find((d) => d.date === key);
|
|
8019
|
+
if (day) for (const m of day.models || []) todayTokens += Number(m.totalTokens) || 0;
|
|
8020
|
+
official = {
|
|
8021
|
+
todayTokens,
|
|
8022
|
+
totalTokens: Number(all && all.summary && all.summary.totalTokens) || 0,
|
|
8023
|
+
totalSessions: Number(all && all.summary && all.summary.totalSessions) || 0
|
|
8024
|
+
};
|
|
8025
|
+
renderBar();
|
|
8026
|
+
} catch {
|
|
8027
|
+
usageSvc = null;
|
|
8028
|
+
}
|
|
8029
|
+
})();
|
|
8030
|
+
}
|
|
8031
|
+
var GLOBAL_GROUP = /* @__PURE__ */ new Set(["todayTokens", "totalTokens", "tasks"]);
|
|
8032
|
+
var SB_ICONS = {
|
|
8033
|
+
ctx: '<path d="M21.21 15.89A10 10 0 1 1 8 2.83"/><path d="M22 12A10 10 0 0 0 12 2v10z"/>',
|
|
8034
|
+
asks: '<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/>',
|
|
8035
|
+
today: '<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',
|
|
8036
|
+
total: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/>',
|
|
8037
|
+
tasks: '<rect x="3" y="5" width="6" height="6" rx="1"/><path d="m3 17 2 2 4-4"/><path d="M13 6h8"/><path d="M13 12h8"/><path d="M13 18h8"/>',
|
|
8038
|
+
coins: '<circle cx="8" cy="8" r="6"/><path d="M18.09 10.37A6 6 0 1 1 10.34 18"/><path d="M7 6h1v4"/><path d="m16.71 13.88.7.71-2.82 2.82"/>'
|
|
8039
|
+
};
|
|
8040
|
+
var sbIcon = (name) => `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="zcodepro-sb-icon">${SB_ICONS[name]}</svg>`;
|
|
8041
|
+
function fmtTokens(n) {
|
|
8042
|
+
if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
|
|
8043
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
8044
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
8045
|
+
return String(n);
|
|
8046
|
+
}
|
|
8047
|
+
function fmtNum(n) {
|
|
8048
|
+
if (!isZhLocale()) return fmtTokens(n);
|
|
8049
|
+
if (n < 1e4) return String(n);
|
|
8050
|
+
if (n >= 1e8) {
|
|
8051
|
+
const yi = Math.round(n / 1e8 * 10) / 10;
|
|
8052
|
+
return (yi % 1 === 0 ? String(yi) : yi.toFixed(1)) + "\u4EBF";
|
|
8053
|
+
}
|
|
8054
|
+
const wan = Math.round(n / 1e4 * 10) / 10;
|
|
8055
|
+
return (wan % 1 === 0 ? String(wan) : wan.toFixed(1)) + "\u4E07";
|
|
8056
|
+
}
|
|
8057
|
+
function itemContent(id, L) {
|
|
8058
|
+
const g = lastStats && lastStats.global;
|
|
8059
|
+
const label = (text) => `<em>${text}</em>`;
|
|
8060
|
+
switch (id) {
|
|
8061
|
+
case "ctx": {
|
|
8062
|
+
const dom = readCtx();
|
|
8063
|
+
if (dom) {
|
|
8064
|
+
const pct = Math.round(dom.used / dom.size * 1e3) / 10;
|
|
8065
|
+
const tone = pct >= 95 ? "danger" : pct >= 80 ? "warn" : "";
|
|
8066
|
+
return {
|
|
8067
|
+
html: sbIcon("ctx") + label(L.sbLabelCtx) + `<b>${fmtNum(dom.used)}/${fmtNum(dom.size)}${isZhLocale() ? "\uFF08" : "("}${pct}%${isZhLocale() ? "\uFF09" : ")"}</b>`,
|
|
8068
|
+
title: `${L.sbItemCtx}\uFF1A${dom.used.toLocaleString()} / ${dom.size.toLocaleString()}`,
|
|
8069
|
+
tone
|
|
8070
|
+
};
|
|
8071
|
+
}
|
|
8072
|
+
return null;
|
|
8073
|
+
}
|
|
8074
|
+
case "questions": {
|
|
8075
|
+
const nav = document.querySelector('[data-testid="v4-turn-navigator"]');
|
|
8076
|
+
const n = nav ? Number(nav.getAttribute("data-item-count")) : 0;
|
|
8077
|
+
return n > 0 ? { html: sbIcon("asks") + label(L.sbLabelQuestions) + String(n), title: L.sbItemQuestions } : null;
|
|
8078
|
+
}
|
|
8079
|
+
case "todayTokens": {
|
|
8080
|
+
const n = official ? official.todayTokens : g ? g.todayTokens : 0;
|
|
8081
|
+
return n > 0 ? { html: sbIcon("today") + label(L.sbLabelToday) + fmtNum(n), title: L.sbItemTodayTokens } : null;
|
|
8082
|
+
}
|
|
8083
|
+
case "totalTokens": {
|
|
8084
|
+
const n = official ? official.totalTokens : g ? g.totalTokens : 0;
|
|
8085
|
+
return n > 0 ? { html: sbIcon("total") + label(L.sbLabelTotal) + fmtNum(n), title: L.sbItemTotalTokens } : null;
|
|
8086
|
+
}
|
|
8087
|
+
case "tasks": {
|
|
8088
|
+
const n = official ? official.totalSessions : g ? g.tasks : 0;
|
|
8089
|
+
return n > 0 ? { html: sbIcon("tasks") + label(L.sbLabelTasks) + String(n), title: L.sbItemTasks } : null;
|
|
8090
|
+
}
|
|
8091
|
+
default:
|
|
8092
|
+
return null;
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
function renderBar() {
|
|
8096
|
+
const ta = document.querySelector("textarea, [contenteditable=true]");
|
|
8097
|
+
const host = ta && (ta.closest("form") || ta.parentElement);
|
|
8098
|
+
if (!enabled4 || !host || !host.parentElement) {
|
|
8099
|
+
if (barEl) barEl.remove();
|
|
8100
|
+
barEl = null;
|
|
8101
|
+
return;
|
|
8102
|
+
}
|
|
8103
|
+
if (!barEl || !barEl.isConnected) {
|
|
8104
|
+
if (!barEl) {
|
|
8105
|
+
barEl = document.createElement("div");
|
|
8106
|
+
barEl.className = "zcodepro-statusbar";
|
|
8107
|
+
}
|
|
8108
|
+
host.parentElement.insertBefore(barEl, host.nextSibling);
|
|
8109
|
+
}
|
|
8110
|
+
const hasSession = !![...document.querySelectorAll("[data-task-item-key]")].find((e) => (e.className + "").includes("bg-selected"));
|
|
8111
|
+
barEl.style.marginBottom = hasSession ? "-14px" : "0";
|
|
8112
|
+
barEl.style.paddingBottom = hasSession ? "0" : "7px";
|
|
8113
|
+
const L = t();
|
|
8114
|
+
const parts = [];
|
|
8115
|
+
let lastGroup = "";
|
|
8116
|
+
for (const it of items) {
|
|
8117
|
+
if (!it.on) continue;
|
|
8118
|
+
const c = itemContent(it.id, L);
|
|
8119
|
+
if (!c) continue;
|
|
8120
|
+
const group = GLOBAL_GROUP.has(it.id) ? "g" : "s";
|
|
8121
|
+
if (lastGroup && group !== lastGroup) parts.push('<span class="zcodepro-statusbar-groupsep"></span>');
|
|
8122
|
+
lastGroup = group;
|
|
8123
|
+
parts.push(`<span title="${c.title.replace(/"/g, """)}"${c.tone ? ` data-tone="${c.tone}"` : ""}>${c.html}</span>`);
|
|
8124
|
+
}
|
|
8125
|
+
const SEP = '<span class="zcodepro-statusbar-sep">\xB7</span>';
|
|
8126
|
+
const GROUPSEP = '<span class="zcodepro-statusbar-groupsep"></span>';
|
|
8127
|
+
barEl.innerHTML = parts.reduce((acc, p, i) => {
|
|
8128
|
+
if (i === 0) return p;
|
|
8129
|
+
if (p === GROUPSEP || parts[i - 1] === GROUPSEP) return acc + p;
|
|
8130
|
+
return acc + SEP + p;
|
|
8131
|
+
}, "");
|
|
8132
|
+
barEl.style.display = parts.length ? "" : "none";
|
|
8133
|
+
}
|
|
8134
|
+
async function tick() {
|
|
8135
|
+
if (!enabled4 || document.hidden) return;
|
|
8136
|
+
refreshOfficial();
|
|
8137
|
+
const res = await rpc("/stats/usage").catch(() => null);
|
|
8138
|
+
if (res && res.ok) lastStats = res;
|
|
8139
|
+
renderBar();
|
|
8140
|
+
}
|
|
8141
|
+
function startStatusBar() {
|
|
8142
|
+
ensureStyle();
|
|
8143
|
+
const refreshCfg = () => {
|
|
8144
|
+
void getConfig().then((cfg) => {
|
|
8145
|
+
enabled4 = cfg.features ? cfg.features.statusBar !== false : true;
|
|
8146
|
+
const saved = cfg.statusBar && Array.isArray(cfg.statusBar.items) ? cfg.statusBar.items : null;
|
|
8147
|
+
if (saved) {
|
|
8148
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
8149
|
+
const list = saved.filter((x) => DEFAULT_STATUS_ITEMS.some((d) => d.id === x.id)).map((x) => ({ ...x }));
|
|
8150
|
+
const known = new Set(list.map((x) => x.id));
|
|
8151
|
+
for (const d of DEFAULT_STATUS_ITEMS) {
|
|
8152
|
+
if (!known.has(d.id)) list.push({ ...d });
|
|
8153
|
+
}
|
|
8154
|
+
items = [
|
|
8155
|
+
...list.filter((x) => !GLOBAL_GROUP.has(x.id)),
|
|
8156
|
+
...list.filter((x) => GLOBAL_GROUP.has(x.id))
|
|
8157
|
+
];
|
|
8158
|
+
} else {
|
|
8159
|
+
items = DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
8160
|
+
}
|
|
8161
|
+
renderBar();
|
|
8162
|
+
}).catch(() => {
|
|
8163
|
+
});
|
|
8164
|
+
};
|
|
8165
|
+
refreshCfg();
|
|
8166
|
+
window.addEventListener("zcodepro:config-changed", refreshCfg);
|
|
8167
|
+
document.addEventListener("visibilitychange", () => {
|
|
8168
|
+
if (!document.hidden) void tick();
|
|
8169
|
+
});
|
|
8170
|
+
setInterval(() => {
|
|
8171
|
+
void tick();
|
|
8172
|
+
}, 2e3);
|
|
8173
|
+
let rerenderTimer = 0;
|
|
8174
|
+
new MutationObserver(() => {
|
|
8175
|
+
if (rerenderTimer) return;
|
|
8176
|
+
rerenderTimer = setTimeout(() => {
|
|
8177
|
+
rerenderTimer = 0;
|
|
8178
|
+
renderBar();
|
|
8179
|
+
}, 300);
|
|
8180
|
+
}).observe(document.body, { childList: true, subtree: true });
|
|
8181
|
+
}
|
|
8182
|
+
|
|
8183
|
+
// src/inject/features/turn-usage.js
|
|
8184
|
+
var enabled5 = true;
|
|
8185
|
+
var recentTurns = [];
|
|
8186
|
+
var scanTimer = 0;
|
|
8187
|
+
var turnCfg = [
|
|
8188
|
+
{ id: "turnIn", on: true },
|
|
8189
|
+
{ id: "turnOut", on: true },
|
|
8190
|
+
{ id: "turnCache", on: true }
|
|
8191
|
+
];
|
|
8192
|
+
var refreshTurnItems = () => {
|
|
8193
|
+
void getConfig().then((cfg) => {
|
|
8194
|
+
const saved = cfg.statusBar && Array.isArray(cfg.statusBar.turnItems) ? cfg.statusBar.turnItems : null;
|
|
8195
|
+
if (!saved) return;
|
|
8196
|
+
const known = new Set(turnCfg.map((x) => x.id));
|
|
8197
|
+
const list = saved.filter((x) => x && known.has(x.id)).map((x) => ({ id: x.id, on: x.on !== false }));
|
|
8198
|
+
for (const d of turnCfg) if (!list.some((x) => x.id === d.id)) list.push({ ...d });
|
|
8199
|
+
turnCfg = list;
|
|
8200
|
+
}).catch(() => {
|
|
8201
|
+
});
|
|
8202
|
+
};
|
|
8203
|
+
var ICONS = {
|
|
8204
|
+
up: '<path d="m5 12 7-7 7 7"/><path d="M12 19V5"/>',
|
|
8205
|
+
down: '<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>',
|
|
8206
|
+
cache: '<path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/>'
|
|
8207
|
+
};
|
|
8208
|
+
var icon = (name) => `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:11px;height:11px;vertical-align:-1.5px;opacity:.6">${ICONS[name]}</svg>`;
|
|
8209
|
+
function fmt(n) {
|
|
8210
|
+
if (!isZhLocale()) {
|
|
8211
|
+
if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
|
|
8212
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
8213
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
8214
|
+
return String(n);
|
|
8215
|
+
}
|
|
8216
|
+
if (n >= 1e8) return (n / 1e8).toFixed(1) + "\u4EBF";
|
|
8217
|
+
if (n >= 1e4) {
|
|
8218
|
+
const wan = Math.round(n / 1e4 * 10) / 10;
|
|
8219
|
+
return (wan % 1 === 0 ? String(wan) : wan.toFixed(1)) + "\u4E07";
|
|
8220
|
+
}
|
|
8221
|
+
return String(n);
|
|
8222
|
+
}
|
|
8223
|
+
function findRows() {
|
|
8224
|
+
const rows = [];
|
|
8225
|
+
for (const btn of document.querySelectorAll('[data-testid^="v4-copy-"]')) {
|
|
8226
|
+
const row = btn.parentElement;
|
|
8227
|
+
if (!row || row.dataset.zcodeproTurn) continue;
|
|
8228
|
+
if (!row.querySelector('[data-testid^="v4-feedback-"]')) continue;
|
|
8229
|
+
const timeEl = [...row.querySelectorAll("span")].find((s) => /\d{1,2}:\d{2}$/.test((s.textContent || "").trim()));
|
|
8230
|
+
if (timeEl) {
|
|
8231
|
+
const ts = rowTimeTs((timeEl.textContent || "").trim());
|
|
8232
|
+
if (ts != null) rows.push({ row, ts });
|
|
8233
|
+
}
|
|
8234
|
+
}
|
|
8235
|
+
return rows;
|
|
8236
|
+
}
|
|
8237
|
+
function currentSessionId() {
|
|
8238
|
+
const rows = [...document.querySelectorAll("[data-task-item-key]")];
|
|
8239
|
+
const cur = rows.find((e) => (e.className + "").includes("bg-selected")) || rows[rows.length - 1];
|
|
8240
|
+
const key = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
8241
|
+
const i = key.lastIndexOf(":sess");
|
|
8242
|
+
return i > 0 ? key.slice(i + 1) : "";
|
|
8243
|
+
}
|
|
8244
|
+
function injectRow(row, bucket) {
|
|
8245
|
+
row.dataset.zcodeproTurn = "1";
|
|
8246
|
+
if (!bucket || bucket.in + bucket.out <= 0) return;
|
|
8247
|
+
const L = t();
|
|
8248
|
+
const el = document.createElement("span");
|
|
8249
|
+
el.dataset.zcodeproTurnSpan = "1";
|
|
8250
|
+
el.className = "select-none text-ui-sm text-foreground-subtlest";
|
|
8251
|
+
el.style.whiteSpace = "nowrap";
|
|
8252
|
+
el.style.display = "inline-flex";
|
|
8253
|
+
el.style.alignItems = "center";
|
|
8254
|
+
el.style.gap = "4px";
|
|
8255
|
+
el.style.marginLeft = "10px";
|
|
8256
|
+
const cachePct = bucket.in > 0 && bucket.cacheRead > 0 ? (bucket.cacheRead / bucket.in * 100).toFixed(2) : "";
|
|
8257
|
+
const group = (html) => `<span style="display:inline-flex;align-items:center;gap:2px">${html}</span>`;
|
|
8258
|
+
const em = (text) => `<em style="font-style:normal;opacity:.75">${text}</em>`;
|
|
8259
|
+
const DOT = '<span style="opacity:.45">\xB7</span>';
|
|
8260
|
+
const sections = [];
|
|
8261
|
+
for (const s of turnCfg) {
|
|
8262
|
+
if (!s.on) continue;
|
|
8263
|
+
if (s.id === "turnIn") sections.push(group(icon("up") + em(L.sbLabelIn) + fmt(bucket.in)));
|
|
8264
|
+
else if (s.id === "turnOut") sections.push(group(icon("down") + em(L.sbLabelOut) + fmt(bucket.out)));
|
|
8265
|
+
else if (s.id === "turnCache" && cachePct) sections.push(group(icon("cache") + em(L.sbLabelCache) + cachePct + "%"));
|
|
8266
|
+
}
|
|
8267
|
+
if (!sections.length) {
|
|
8268
|
+
delete row.dataset.zcodeproTurn;
|
|
8269
|
+
el.remove();
|
|
8270
|
+
return;
|
|
8271
|
+
}
|
|
8272
|
+
const VBAR = '<span style="display:inline-block;width:1px;height:10px;background:currentColor;opacity:.3;margin:0 5px"></span>';
|
|
8273
|
+
el.innerHTML = VBAR + sections.join(DOT);
|
|
8274
|
+
el.title = `${L.turnUsageTitle}\uFF1A${L.sbLabelIn} ${bucket.in.toLocaleString()} / ${L.sbLabelOut} ${bucket.out.toLocaleString()}` + (bucket.cacheRead > 0 ? ` / ${L.sbLabelCache} ${bucket.cacheRead.toLocaleString()}` : "");
|
|
8275
|
+
row.append(el);
|
|
8276
|
+
}
|
|
8277
|
+
function rowTimeTs(text) {
|
|
8278
|
+
const now = /* @__PURE__ */ new Date();
|
|
8279
|
+
let m = text.match(/^(\d{1,2}):(\d{2})$/);
|
|
8280
|
+
if (m) return new Date(now.getFullYear(), now.getMonth(), now.getDate(), +m[1], +m[2]).getTime();
|
|
8281
|
+
m = text.match(/^昨天\s*(\d{1,2}):(\d{2})$/);
|
|
8282
|
+
if (m) {
|
|
8283
|
+
const y = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
8284
|
+
return new Date(y.getFullYear(), y.getMonth(), y.getDate(), +m[1], +m[2]).getTime();
|
|
8285
|
+
}
|
|
8286
|
+
m = text.match(/^(\d{1,2})\/(\d{1,2})\s*(\d{1,2}):(\d{2})$/);
|
|
8287
|
+
if (m) return new Date(now.getFullYear(), +m[1] - 1, +m[2], +m[3], +m[4]).getTime();
|
|
8288
|
+
return null;
|
|
8289
|
+
}
|
|
8290
|
+
var lastSid = "";
|
|
8291
|
+
function scan3() {
|
|
8292
|
+
if (!enabled5) return;
|
|
8293
|
+
const sid = currentSessionId();
|
|
8294
|
+
if (sid !== lastSid) {
|
|
8295
|
+
lastSid = sid;
|
|
8296
|
+
recentTurns = [];
|
|
8297
|
+
void tick2();
|
|
8298
|
+
}
|
|
8299
|
+
for (const el of document.querySelectorAll('[data-zcodepro-turn-span], span[title^="\u672C\u8F6E"], span[title^="Turn"]')) el.remove();
|
|
8300
|
+
for (const row of document.querySelectorAll("[data-zcodepro-turn]")) delete row.dataset.zcodeproTurn;
|
|
8301
|
+
if (document.hidden || !recentTurns.length) return;
|
|
8302
|
+
const rows = findRows().sort((a, b) => a.ts - b.ts);
|
|
8303
|
+
if (!rows.length) return;
|
|
8304
|
+
const agg = rows.map(() => ({ in: 0, out: 0, cacheRead: 0 }));
|
|
8305
|
+
const dayOf = (t2) => {
|
|
8306
|
+
const d = new Date(t2);
|
|
8307
|
+
return d.getFullYear() * 1e4 + (d.getMonth() + 1) * 100 + d.getDate();
|
|
8308
|
+
};
|
|
8309
|
+
for (const b of recentTurns) {
|
|
8310
|
+
let owner = -1;
|
|
8311
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8312
|
+
if (rows[i].ts <= b.ts) owner = i;
|
|
8313
|
+
else break;
|
|
8314
|
+
}
|
|
8315
|
+
if (owner < 0) continue;
|
|
8316
|
+
if (dayOf(rows[owner].ts) !== dayOf(b.ts)) continue;
|
|
8317
|
+
agg[owner].in += b.in;
|
|
8318
|
+
agg[owner].out += b.out;
|
|
8319
|
+
agg[owner].cacheRead += b.cacheRead;
|
|
8320
|
+
}
|
|
8321
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8322
|
+
if (agg[i].in + agg[i].out > 0) injectRow(rows[i].row, agg[i]);
|
|
8323
|
+
}
|
|
8324
|
+
}
|
|
8325
|
+
async function tick2() {
|
|
8326
|
+
if (!enabled5 || document.hidden) return;
|
|
8327
|
+
const sid = currentSessionId();
|
|
8328
|
+
const res = await rpc("/stats/usage" + (sid ? "?session=" + encodeURIComponent(sid) : "")).catch(() => null);
|
|
8329
|
+
if (res && res.ok && Array.isArray(res.recentTurns)) {
|
|
8330
|
+
recentTurns = res.recentTurns;
|
|
8331
|
+
scan3();
|
|
8332
|
+
}
|
|
8333
|
+
}
|
|
8334
|
+
function startTurnUsage() {
|
|
8335
|
+
void getConfig().then((cfg) => {
|
|
8336
|
+
enabled5 = cfg.features ? cfg.features.statusBar !== false : true;
|
|
8337
|
+
}).catch(() => {
|
|
8338
|
+
});
|
|
8339
|
+
refreshTurnItems();
|
|
8340
|
+
window.addEventListener("zcodepro:config-changed", () => {
|
|
8341
|
+
void getConfig().then((cfg) => {
|
|
8342
|
+
enabled5 = cfg.features ? cfg.features.statusBar !== false : true;
|
|
8343
|
+
}).catch(() => {
|
|
8344
|
+
});
|
|
8345
|
+
refreshTurnItems();
|
|
8346
|
+
});
|
|
8347
|
+
const observer2 = new MutationObserver(() => {
|
|
8348
|
+
if (scanTimer) return;
|
|
8349
|
+
scanTimer = setTimeout(() => {
|
|
8350
|
+
scanTimer = 0;
|
|
8351
|
+
scan3();
|
|
8352
|
+
}, 1200);
|
|
8353
|
+
});
|
|
8354
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
8355
|
+
setInterval(() => {
|
|
8356
|
+
void tick2();
|
|
8357
|
+
}, 5e3);
|
|
8358
|
+
document.addEventListener("visibilitychange", () => {
|
|
8359
|
+
if (!document.hidden) void tick2();
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8362
|
+
|
|
7618
8363
|
// src/inject/features/title-lock.js
|
|
7619
8364
|
var TASK_SEL2 = "[data-task-item-key]";
|
|
7620
8365
|
var SCAN_DEBOUNCE_MS3 = 150;
|
|
@@ -7625,7 +8370,7 @@
|
|
|
7625
8370
|
var MAP_REFRESH_MS = 6e4;
|
|
7626
8371
|
var installed3 = false;
|
|
7627
8372
|
var seenRows = /* @__PURE__ */ new WeakSet();
|
|
7628
|
-
var
|
|
8373
|
+
var enabled6 = true;
|
|
7629
8374
|
var pinned = null;
|
|
7630
8375
|
var resolved = false;
|
|
7631
8376
|
var fetching = null;
|
|
@@ -7640,7 +8385,7 @@
|
|
|
7640
8385
|
const t2 = item.querySelector('[class*="truncate"]');
|
|
7641
8386
|
return t2 ? [t2] : [];
|
|
7642
8387
|
}
|
|
7643
|
-
function
|
|
8388
|
+
function findRows2(key) {
|
|
7644
8389
|
return [...document.querySelectorAll(`${TASK_SEL2}[data-task-item-key="${CSS.escape(key)}"]`)];
|
|
7645
8390
|
}
|
|
7646
8391
|
async function fetchPinned() {
|
|
@@ -7649,8 +8394,8 @@
|
|
|
7649
8394
|
const res = await rpc("/pinned-titles");
|
|
7650
8395
|
if (!res || !res.ok) return null;
|
|
7651
8396
|
resolved = true;
|
|
7652
|
-
|
|
7653
|
-
if (!
|
|
8397
|
+
enabled6 = res.enabled !== false;
|
|
8398
|
+
if (!enabled6) {
|
|
7654
8399
|
pinned = null;
|
|
7655
8400
|
return null;
|
|
7656
8401
|
}
|
|
@@ -7665,7 +8410,7 @@
|
|
|
7665
8410
|
}
|
|
7666
8411
|
}
|
|
7667
8412
|
function isMismatch(item) {
|
|
7668
|
-
if (!
|
|
8413
|
+
if (!enabled6 || !pinned) return null;
|
|
7669
8414
|
const key = item.getAttribute("data-task-item-key") || "";
|
|
7670
8415
|
const want = pinned.get(sessIdOf(key));
|
|
7671
8416
|
if (want === void 0) return null;
|
|
@@ -7683,10 +8428,10 @@
|
|
|
7683
8428
|
}
|
|
7684
8429
|
function scheduleEnforce(key, { immediate = false } = {}) {
|
|
7685
8430
|
if (immediate) {
|
|
7686
|
-
if (
|
|
8431
|
+
if (enabled6 && pinned) {
|
|
7687
8432
|
const want = pinned.get(sessIdOf(key));
|
|
7688
8433
|
if (want !== void 0) {
|
|
7689
|
-
for (const item of
|
|
8434
|
+
for (const item of findRows2(key)) {
|
|
7690
8435
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7691
8436
|
}
|
|
7692
8437
|
}
|
|
@@ -7702,7 +8447,7 @@
|
|
|
7702
8447
|
const want = map.get(sessIdOf(key));
|
|
7703
8448
|
if (want === void 0) return;
|
|
7704
8449
|
let wrote = false;
|
|
7705
|
-
for (const item of
|
|
8450
|
+
for (const item of findRows2(key)) {
|
|
7706
8451
|
if (isMismatch(item) !== key) continue;
|
|
7707
8452
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7708
8453
|
wrote = true;
|
|
@@ -7718,13 +8463,13 @@
|
|
|
7718
8463
|
if (!map) return;
|
|
7719
8464
|
const want = map.get(sessIdOf(key));
|
|
7720
8465
|
if (want === void 0) return;
|
|
7721
|
-
for (const item of
|
|
8466
|
+
for (const item of findRows2(key)) {
|
|
7722
8467
|
if (isMismatch(item) !== key) continue;
|
|
7723
8468
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7724
8469
|
}
|
|
7725
8470
|
}
|
|
7726
|
-
function
|
|
7727
|
-
if (!
|
|
8471
|
+
function scan4() {
|
|
8472
|
+
if (!enabled6 || !pinned || pinned.size === 0) return;
|
|
7728
8473
|
for (const item of document.querySelectorAll(TASK_SEL2)) {
|
|
7729
8474
|
const key = isMismatch(item);
|
|
7730
8475
|
if (!key) {
|
|
@@ -7758,23 +8503,23 @@
|
|
|
7758
8503
|
if (scanDebounce3) return;
|
|
7759
8504
|
scanDebounce3 = setTimeout(() => {
|
|
7760
8505
|
scanDebounce3 = 0;
|
|
7761
|
-
|
|
8506
|
+
scan4();
|
|
7762
8507
|
}, SCAN_DEBOUNCE_MS3);
|
|
7763
8508
|
}
|
|
7764
8509
|
var mapRefreshTimer = 0;
|
|
7765
8510
|
function refreshMapSoon() {
|
|
7766
8511
|
if (mapRefreshTimer) return;
|
|
7767
|
-
const
|
|
8512
|
+
const tick6 = () => {
|
|
7768
8513
|
if (document.hidden) {
|
|
7769
|
-
mapRefreshTimer = setTimeout(
|
|
8514
|
+
mapRefreshTimer = setTimeout(tick6, 1e4);
|
|
7770
8515
|
return;
|
|
7771
8516
|
}
|
|
7772
8517
|
mapRefreshTimer = 0;
|
|
7773
|
-
if (
|
|
7774
|
-
if (m)
|
|
8518
|
+
if (enabled6 && resolved) void fetchPinned().then((m) => {
|
|
8519
|
+
if (m) scan4();
|
|
7775
8520
|
});
|
|
7776
8521
|
};
|
|
7777
|
-
mapRefreshTimer = setTimeout(
|
|
8522
|
+
mapRefreshTimer = setTimeout(tick6, MAP_REFRESH_MS);
|
|
7778
8523
|
}
|
|
7779
8524
|
var editingKey = null;
|
|
7780
8525
|
var bootDelay = 0;
|
|
@@ -7788,16 +8533,16 @@
|
|
|
7788
8533
|
}
|
|
7789
8534
|
async function bootstrap() {
|
|
7790
8535
|
const map = await fetchPinned();
|
|
7791
|
-
if (map)
|
|
8536
|
+
if (map) scan4();
|
|
7792
8537
|
}
|
|
7793
8538
|
function setRowTitle(key, text) {
|
|
7794
|
-
for (const item of
|
|
8539
|
+
for (const item of findRows2(key)) {
|
|
7795
8540
|
for (const el of titleElsOf(item)) writeTitle(el, text);
|
|
7796
8541
|
}
|
|
7797
8542
|
}
|
|
7798
8543
|
function refreshPinnedTitles() {
|
|
7799
8544
|
return fetchPinned().then((m) => {
|
|
7800
|
-
if (m)
|
|
8545
|
+
if (m) scan4();
|
|
7801
8546
|
});
|
|
7802
8547
|
}
|
|
7803
8548
|
var RENAME_CTX_VALID_MS = 15e3;
|
|
@@ -7816,7 +8561,7 @@
|
|
|
7816
8561
|
renameCtx = null;
|
|
7817
8562
|
return;
|
|
7818
8563
|
}
|
|
7819
|
-
if (!
|
|
8564
|
+
if (!enabled6 || !pinned) return;
|
|
7820
8565
|
const want = pinned.get(sessIdOf(renameCtx.key));
|
|
7821
8566
|
if (want === void 0) return;
|
|
7822
8567
|
for (const el of document.querySelectorAll('[role="dialog"] input, [role="dialog"] textarea, [role="dialog"] [contenteditable="true"]')) {
|
|
@@ -7854,10 +8599,10 @@
|
|
|
7854
8599
|
}, true);
|
|
7855
8600
|
scheduleBootRetry();
|
|
7856
8601
|
setInterval(() => {
|
|
7857
|
-
if (!document.hidden)
|
|
8602
|
+
if (!document.hidden) scan4();
|
|
7858
8603
|
}, SCAN_FALLBACK_MS3);
|
|
7859
8604
|
document.addEventListener("visibilitychange", () => {
|
|
7860
|
-
if (!document.hidden)
|
|
8605
|
+
if (!document.hidden) scan4();
|
|
7861
8606
|
});
|
|
7862
8607
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
7863
8608
|
void bootstrap();
|
|
@@ -7873,7 +8618,7 @@
|
|
|
7873
8618
|
if (editingKey === null) return;
|
|
7874
8619
|
editingKey = null;
|
|
7875
8620
|
void fetchPinned().then((m) => {
|
|
7876
|
-
if (m)
|
|
8621
|
+
if (m) scan4();
|
|
7877
8622
|
});
|
|
7878
8623
|
});
|
|
7879
8624
|
}
|
|
@@ -8104,7 +8849,7 @@
|
|
|
8104
8849
|
await reclaim(ws);
|
|
8105
8850
|
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
8106
8851
|
}
|
|
8107
|
-
async function
|
|
8852
|
+
async function tick3() {
|
|
8108
8853
|
const cfg = await getConfig();
|
|
8109
8854
|
if ((cfg.features || {}).idleReclaim === false) {
|
|
8110
8855
|
idleSince.clear();
|
|
@@ -8166,20 +8911,171 @@
|
|
|
8166
8911
|
}
|
|
8167
8912
|
function startIdleReclaim() {
|
|
8168
8913
|
const loop = () => {
|
|
8169
|
-
|
|
8914
|
+
tick3().catch(() => {
|
|
8170
8915
|
});
|
|
8171
8916
|
};
|
|
8172
8917
|
loop();
|
|
8173
8918
|
setInterval(loop, CHECK_MS);
|
|
8174
8919
|
}
|
|
8175
8920
|
|
|
8921
|
+
// src/inject/features/sandbox-reclaim.js
|
|
8922
|
+
var CHECK_MS2 = 3e4;
|
|
8923
|
+
var MIN_BUDGET = 8;
|
|
8924
|
+
var MAX_BUDGET = 64;
|
|
8925
|
+
var RETRY_COOLDOWN_MS = 10 * 6e4;
|
|
8926
|
+
var SEEN_KEY = "zcodepro:sbx-seen";
|
|
8927
|
+
var seen = /* @__PURE__ */ new Map();
|
|
8928
|
+
function loadSeen() {
|
|
8929
|
+
try {
|
|
8930
|
+
const raw = JSON.parse(localStorage.getItem(SEEN_KEY) || "{}");
|
|
8931
|
+
for (const [id, v] of Object.entries(raw)) {
|
|
8932
|
+
if (id && v && Number.isFinite(v.firstSeen)) seen.set(id, { initId: v.initId, firstSeen: v.firstSeen });
|
|
8933
|
+
}
|
|
8934
|
+
} catch {
|
|
8935
|
+
}
|
|
8936
|
+
}
|
|
8937
|
+
var saveSeenTimer = null;
|
|
8938
|
+
function saveSeenSoon() {
|
|
8939
|
+
if (saveSeenTimer) return;
|
|
8940
|
+
saveSeenTimer = setTimeout(() => {
|
|
8941
|
+
saveSeenTimer = null;
|
|
8942
|
+
try {
|
|
8943
|
+
const out = {};
|
|
8944
|
+
for (const [id, v] of seen) out[id] = v;
|
|
8945
|
+
localStorage.setItem(SEEN_KEY, JSON.stringify(out));
|
|
8946
|
+
} catch {
|
|
8947
|
+
}
|
|
8948
|
+
}, 2e3);
|
|
8949
|
+
}
|
|
8950
|
+
var cooldown = /* @__PURE__ */ new Map();
|
|
8951
|
+
var disabledLogged = false;
|
|
8952
|
+
function onPortsMessage(e) {
|
|
8953
|
+
const d = e.data;
|
|
8954
|
+
if (!d || d.type !== "zcode:plugin-sandbox-ports" || typeof d.sandboxId !== "string") return;
|
|
8955
|
+
seen.set(d.sandboxId, { initId: Number(d.initId) || 0, firstSeen: Date.now() });
|
|
8956
|
+
saveSeenSoon();
|
|
8957
|
+
}
|
|
8958
|
+
function extractSandboxId(wv) {
|
|
8959
|
+
const m = /instance\/(sb-[0-9a-f]+)\//.exec(wv.getAttribute("src") || "");
|
|
8960
|
+
return m ? m[1] : null;
|
|
8961
|
+
}
|
|
8962
|
+
function isVisible(wv) {
|
|
8963
|
+
const root = wv.closest("[data-sandbox-page-root]");
|
|
8964
|
+
if (!root) return wv.getClientRects().length > 0;
|
|
8965
|
+
if (!root.getClientRects().length) return false;
|
|
8966
|
+
return Number(getComputedStyle(root).opacity) > 0.5;
|
|
8967
|
+
}
|
|
8968
|
+
async function tick4() {
|
|
8969
|
+
const cfg = await getConfig();
|
|
8970
|
+
if ((cfg.features || {}).sandboxReclaim === false) {
|
|
8971
|
+
seen.clear();
|
|
8972
|
+
return;
|
|
8973
|
+
}
|
|
8974
|
+
const bridge = window.zcodePluginSandbox;
|
|
8975
|
+
if (!bridge || typeof bridge.disposeSandbox !== "function") {
|
|
8976
|
+
if (!disabledLogged) {
|
|
8977
|
+
disabledLogged = true;
|
|
8978
|
+
console.info("[zcodepro] sandbox-reclaim: \u5F53\u524D\u7A97\u53E3\u65E0 zcodePluginSandbox \u6865\uFF0C\u6C99\u7BB1\u56DE\u6536\u8DF3\u8FC7");
|
|
8979
|
+
}
|
|
8980
|
+
return;
|
|
8981
|
+
}
|
|
8982
|
+
let budget = Number(cfg.sandboxReclaimBudget);
|
|
8983
|
+
if (!Number.isFinite(budget)) budget = 60;
|
|
8984
|
+
budget = Math.min(MAX_BUDGET, Math.max(MIN_BUDGET, budget));
|
|
8985
|
+
const now = Date.now();
|
|
8986
|
+
const visible = /* @__PURE__ */ new Set();
|
|
8987
|
+
for (const wv of document.querySelectorAll("webview")) {
|
|
8988
|
+
const id = extractSandboxId(wv);
|
|
8989
|
+
if (id) {
|
|
8990
|
+
if (isVisible(wv)) visible.add(id);
|
|
8991
|
+
if (!seen.has(id)) {
|
|
8992
|
+
seen.set(id, { initId: void 0, firstSeen: now });
|
|
8993
|
+
saveSeenSoon();
|
|
8994
|
+
}
|
|
8995
|
+
}
|
|
8996
|
+
}
|
|
8997
|
+
while (seen.size > budget) {
|
|
8998
|
+
let pool = [...seen.keys()].filter((id2) => (cooldown.get(id2) || 0) <= now && !visible.has(id2));
|
|
8999
|
+
if (!pool.length) pool = [...seen.keys()].filter((id2) => (cooldown.get(id2) || 0) <= now);
|
|
9000
|
+
pool.sort((a, b) => ((seen.get(a) || {}).firstSeen || 0) - ((seen.get(b) || {}).firstSeen || 0));
|
|
9001
|
+
if (!pool.length) break;
|
|
9002
|
+
const id = pool[0];
|
|
9003
|
+
const entry = seen.get(id);
|
|
9004
|
+
try {
|
|
9005
|
+
await bridge.disposeSandbox(id, entry && entry.initId);
|
|
9006
|
+
console.info("[zcodepro] sandbox-reclaim: \u767B\u8BB0\u6570 " + seen.size + " \u8D85\u9884\u7B97 " + budget + "\uFF0C\u5DF2\u9A71\u9010\u6700\u65E9\u7684 " + id + (visible.has(id) ? "\uFF08\u53EF\u89C1\uFF0C\u5C5E\u515C\u5E95\uFF09" : ""));
|
|
9007
|
+
} catch (err) {
|
|
9008
|
+
console.warn("[zcodepro] sandbox-reclaim: \u91CA\u653E\u5931\u8D25 " + id, err);
|
|
9009
|
+
seen.delete(id);
|
|
9010
|
+
continue;
|
|
9011
|
+
}
|
|
9012
|
+
seen.delete(id);
|
|
9013
|
+
saveSeenSoon();
|
|
9014
|
+
cooldown.set(id, now + RETRY_COOLDOWN_MS);
|
|
9015
|
+
}
|
|
9016
|
+
if (cooldown.size > 256) {
|
|
9017
|
+
for (const [k, v] of cooldown) {
|
|
9018
|
+
if (v <= now) cooldown.delete(k);
|
|
9019
|
+
}
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
9022
|
+
function startSandboxReclaim() {
|
|
9023
|
+
loadSeen();
|
|
9024
|
+
window.addEventListener("message", onPortsMessage);
|
|
9025
|
+
const loop = () => {
|
|
9026
|
+
tick4().catch(() => {
|
|
9027
|
+
});
|
|
9028
|
+
};
|
|
9029
|
+
loop();
|
|
9030
|
+
setInterval(loop, CHECK_MS2);
|
|
9031
|
+
}
|
|
9032
|
+
|
|
9033
|
+
// src/inject/features/plugin-card-retry.js
|
|
9034
|
+
var SCAN_MS = 15e3;
|
|
9035
|
+
var CLICK_INTERVAL_MS = 3e4;
|
|
9036
|
+
var MARKERS = ["\u63D2\u4EF6\u754C\u9762"];
|
|
9037
|
+
var lastClickAt = 0;
|
|
9038
|
+
function failedRetryButtons() {
|
|
9039
|
+
const out = [];
|
|
9040
|
+
for (const btn of document.querySelectorAll("button")) {
|
|
9041
|
+
if ((btn.textContent || "").trim() !== "\u91CD\u65B0\u52A0\u8F7D") continue;
|
|
9042
|
+
let anc = btn;
|
|
9043
|
+
for (let i = 0; i < 4 && anc.parentElement; i++) {
|
|
9044
|
+
anc = anc.parentElement;
|
|
9045
|
+
const ctx = anc.textContent || "";
|
|
9046
|
+
if (MARKERS.some((m) => ctx.includes(m))) {
|
|
9047
|
+
out.push(btn);
|
|
9048
|
+
break;
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
9051
|
+
}
|
|
9052
|
+
return out;
|
|
9053
|
+
}
|
|
9054
|
+
async function tick5() {
|
|
9055
|
+
const cfg = await getConfig();
|
|
9056
|
+
if ((cfg.features || {}).pluginCardRetry === false) return;
|
|
9057
|
+
const now = Date.now();
|
|
9058
|
+
if (now - lastClickAt < CLICK_INTERVAL_MS) return;
|
|
9059
|
+
for (const btn of failedRetryButtons()) {
|
|
9060
|
+
lastClickAt = now;
|
|
9061
|
+
btn.click();
|
|
9062
|
+
break;
|
|
9063
|
+
}
|
|
9064
|
+
}
|
|
9065
|
+
function startPluginCardRetry() {
|
|
9066
|
+
setInterval(() => {
|
|
9067
|
+
tick5().catch(() => {
|
|
9068
|
+
});
|
|
9069
|
+
}, SCAN_MS);
|
|
9070
|
+
}
|
|
9071
|
+
|
|
8176
9072
|
// src/inject/features/toolbar-icons.js
|
|
8177
9073
|
var HIDE_CLASS = "zcodepro-tb-hidden";
|
|
8178
9074
|
var SYNC_DEBOUNCE_MS = 150;
|
|
8179
9075
|
var SCAN_FALLBACK_MS5 = 5e3;
|
|
8180
9076
|
var ROW_SEL = "[data-task-item-key]";
|
|
8181
9077
|
var MENU_SEL = '[data-testid="task-new-button"], [data-testid="automations-open"], [data-testid="plugin-store-sidebar-open"], [data-testid="sidebar-search-open"], [data-slot="command"], [data-testid="desktop-top-nav-back"]';
|
|
8182
|
-
var
|
|
9078
|
+
var enabled7 = true;
|
|
8183
9079
|
var rowEl = null;
|
|
8184
9080
|
var origs = null;
|
|
8185
9081
|
var syncTimer = 0;
|
|
@@ -8287,8 +9183,8 @@
|
|
|
8287
9183
|
}
|
|
8288
9184
|
});
|
|
8289
9185
|
const newBtn = mk("newTask", parts.newTask, "span.truncate", L.tbNewTask);
|
|
8290
|
-
const
|
|
8291
|
-
if (
|
|
9186
|
+
const icon2 = iconOf(parts.newTask);
|
|
9187
|
+
if (icon2) newBtn.append(icon2);
|
|
8292
9188
|
const searchBtn = mk("search", parts.search, "span.truncate", L.tbSearch);
|
|
8293
9189
|
const sIcon = iconOf(parts.search);
|
|
8294
9190
|
if (sIcon) searchBtn.append(sIcon);
|
|
@@ -8322,7 +9218,7 @@
|
|
|
8322
9218
|
return scroll.getBoundingClientRect().width < NARROW_SIDEBAR_PX;
|
|
8323
9219
|
}
|
|
8324
9220
|
function sync() {
|
|
8325
|
-
if (!
|
|
9221
|
+
if (!enabled7) return;
|
|
8326
9222
|
const parts = findParts();
|
|
8327
9223
|
if (!parts) {
|
|
8328
9224
|
if (rowEl) rowEl.style.display = "none";
|
|
@@ -8384,8 +9280,8 @@
|
|
|
8384
9280
|
}
|
|
8385
9281
|
async function refreshConfig2() {
|
|
8386
9282
|
const cfg = await getConfig(true).catch(() => null);
|
|
8387
|
-
|
|
8388
|
-
if (
|
|
9283
|
+
enabled7 = !cfg || !cfg.features || cfg.features.toolbarIcons !== false;
|
|
9284
|
+
if (enabled7) sync();
|
|
8389
9285
|
else teardown();
|
|
8390
9286
|
}
|
|
8391
9287
|
function startToolbarIcons() {
|
|
@@ -8411,7 +9307,7 @@
|
|
|
8411
9307
|
var STORE_KEY = "zcodepro:pinned-collapsed";
|
|
8412
9308
|
var SYNC_DEBOUNCE_MS2 = 300;
|
|
8413
9309
|
var SCAN_FALLBACK_MS6 = 5e3;
|
|
8414
|
-
var
|
|
9310
|
+
var enabled8 = true;
|
|
8415
9311
|
var syncTimer2 = 0;
|
|
8416
9312
|
function findPinnedHeader() {
|
|
8417
9313
|
for (const h3 of document.querySelectorAll("h3")) {
|
|
@@ -8468,7 +9364,7 @@
|
|
|
8468
9364
|
}
|
|
8469
9365
|
h3.classList.add(HEAD_CLASS);
|
|
8470
9366
|
h3.addEventListener("click", () => {
|
|
8471
|
-
if (
|
|
9367
|
+
if (enabled8) toggle();
|
|
8472
9368
|
});
|
|
8473
9369
|
const btn = h("button", {
|
|
8474
9370
|
type: "button",
|
|
@@ -8477,7 +9373,7 @@
|
|
|
8477
9373
|
"aria-expanded": collapsed ? "false" : "true",
|
|
8478
9374
|
onClick: (e) => {
|
|
8479
9375
|
e.stopPropagation();
|
|
8480
|
-
if (
|
|
9376
|
+
if (enabled8) toggle();
|
|
8481
9377
|
}
|
|
8482
9378
|
});
|
|
8483
9379
|
btn.append(chevronSvg());
|
|
@@ -8485,7 +9381,7 @@
|
|
|
8485
9381
|
return true;
|
|
8486
9382
|
}
|
|
8487
9383
|
function sync2() {
|
|
8488
|
-
if (
|
|
9384
|
+
if (enabled8) apply2();
|
|
8489
9385
|
}
|
|
8490
9386
|
function scheduleSync2() {
|
|
8491
9387
|
if (syncTimer2) return;
|
|
@@ -8514,8 +9410,8 @@
|
|
|
8514
9410
|
}
|
|
8515
9411
|
async function refreshConfig3() {
|
|
8516
9412
|
const cfg = await getConfig(true).catch(() => null);
|
|
8517
|
-
|
|
8518
|
-
if (
|
|
9413
|
+
enabled8 = !cfg || !cfg.features || cfg.features.pinnedCollapse !== false;
|
|
9414
|
+
if (enabled8) sync2();
|
|
8519
9415
|
else teardown2();
|
|
8520
9416
|
}
|
|
8521
9417
|
function startPinnedCollapse() {
|
|
@@ -8550,12 +9446,12 @@
|
|
|
8550
9446
|
return;
|
|
8551
9447
|
}
|
|
8552
9448
|
const sig = status.updates.map((u) => `${u.name}:${u.installed}>${u.latest}`).join(",");
|
|
8553
|
-
let
|
|
9449
|
+
let seen2 = "";
|
|
8554
9450
|
try {
|
|
8555
|
-
|
|
9451
|
+
seen2 = window.localStorage.getItem(NOTIFIED_KEY) || "";
|
|
8556
9452
|
} catch {
|
|
8557
9453
|
}
|
|
8558
|
-
if (
|
|
9454
|
+
if (seen2 === sig) return;
|
|
8559
9455
|
try {
|
|
8560
9456
|
window.localStorage.setItem(NOTIFIED_KEY, sig);
|
|
8561
9457
|
} catch {
|
|
@@ -8630,6 +9526,14 @@
|
|
|
8630
9526
|
startIdleReclaim();
|
|
8631
9527
|
} catch {
|
|
8632
9528
|
}
|
|
9529
|
+
try {
|
|
9530
|
+
startSandboxReclaim();
|
|
9531
|
+
} catch {
|
|
9532
|
+
}
|
|
9533
|
+
try {
|
|
9534
|
+
startPluginCardRetry();
|
|
9535
|
+
} catch {
|
|
9536
|
+
}
|
|
8633
9537
|
try {
|
|
8634
9538
|
startToolbarIcons();
|
|
8635
9539
|
} catch {
|
|
@@ -8638,6 +9542,14 @@
|
|
|
8638
9542
|
startNewtabPanels();
|
|
8639
9543
|
} catch {
|
|
8640
9544
|
}
|
|
9545
|
+
try {
|
|
9546
|
+
startStatusBar();
|
|
9547
|
+
} catch {
|
|
9548
|
+
}
|
|
9549
|
+
try {
|
|
9550
|
+
startTurnUsage();
|
|
9551
|
+
} catch {
|
|
9552
|
+
}
|
|
8641
9553
|
try {
|
|
8642
9554
|
startPinnedCollapse();
|
|
8643
9555
|
} catch {
|