zcode-pro 1.1.0 → 1.2.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/README.en.md +4 -0
- package/README.md +4 -0
- package/dist/inject.js +1182 -78
- package/package.json +1 -1
- package/src/host/helper.mjs +174 -4
- package/src/host/taskIndex.mjs +18 -0
- package/src/inject/core.js +96 -0
- package/src/inject/features/newtab-panels.js +224 -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 +151 -3
- package/src/inject/features/status-bar.js +274 -0
- package/src/inject/features/turn-usage.js +195 -0
- package/src/inject/index.js +10 -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",
|
|
@@ -255,6 +282,38 @@
|
|
|
255
282
|
switcherUnseen: "\u672A\u67E5\u770B",
|
|
256
283
|
switcherAttentionHint: "\u8FD0\u884C\u4E2D / \u8FD0\u884C\u5B8C\u672A\u67E5\u770B\u7684\u4EFB\u52A1 \xB7 {prev} / {next} \u6216 \u2191 / \u2193 \u9009\u62E9\uFF0CEnter \u6216\u677E\u5F00 alt \u5207\u6362",
|
|
257
284
|
switcherAttentionEmpty: "\u6682\u65E0\u8FD0\u884C\u4E2D\u6216\u672A\u67E5\u770B\u7684\u4EFB\u52A1",
|
|
285
|
+
featureNewtabPanels: "\u65B0\u6807\u7B7E\u9875\u63D2\u4EF6\u9762\u677F\u5165\u53E3",
|
|
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
|
+
ntpDescSuffix: "\u63D2\u4EF6\u9762\u677F",
|
|
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
|
+
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
|
+
tabStylesPane: "\u6837\u5F0F\u8C03\u6574",
|
|
292
|
+
tabStatusPane: "\u72B6\u6001\u680F",
|
|
293
|
+
sbItemCtx: "\u4E0A\u4E0B\u6587\u5360\u7528",
|
|
294
|
+
sbItemQuestions: "\u63D0\u95EE\u6B21\u6570",
|
|
295
|
+
sbGroupSession: "\u4F1A\u8BDD\u7EDF\u8BA1\uFF08\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\uFF09",
|
|
296
|
+
sbGroupGlobal: "\u603B\u7EDF\u8BA1",
|
|
297
|
+
sbGroupTurn: "\u6BCF\u8F6E\u7EDF\u8BA1\uFF08\u56DE\u7B54\u672B\u5C3E\uFF09",
|
|
298
|
+
sbLabelIn: "\u8F93\u5165",
|
|
299
|
+
sbLabelOut: "\u8F93\u51FA",
|
|
300
|
+
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
|
+
turnUsageTitle: "\u672C\u8F6E token",
|
|
304
|
+
sbLabelQuestions: "\u63D0\u95EE",
|
|
305
|
+
sbItemTodayTokens: "\u4ECA\u65E5 token",
|
|
306
|
+
sbItemTasks: "\u4EFB\u52A1\u603B\u6570",
|
|
307
|
+
sbLabelCtx: "\u4E0A\u4E0B\u6587",
|
|
308
|
+
sbLabelTurns: "\u8C03\u7528",
|
|
309
|
+
sbLabelToday: "\u4ECA\u65E5",
|
|
310
|
+
sbLabelTasks: "\u4EFB\u52A1",
|
|
311
|
+
sbItemTotalTokens: "\u7D2F\u8BA1 token",
|
|
312
|
+
sbLabelTotal: "\u7D2F\u8BA1",
|
|
313
|
+
sbMoveUp: "\u4E0A\u79FB",
|
|
314
|
+
sbMoveDown: "\u4E0B\u79FB",
|
|
315
|
+
sbVisible: "\u663E\u793A",
|
|
316
|
+
sbHidden: "\u9690\u85CF",
|
|
258
317
|
tabShortcuts: "\u5FEB\u6377\u952E",
|
|
259
318
|
hkTitle: "\u4F1A\u8BDD\u5FEB\u6377\u5207\u6362",
|
|
260
319
|
hkAltZ: "\u5728\u5F53\u524D\u4E0E\u4E0A\u6B21\u4F7F\u7528\u7684\u4F1A\u8BDD\u95F4\u6765\u56DE\u5207\u6362",
|
|
@@ -655,6 +714,11 @@
|
|
|
655
714
|
tbPluginStore: "Plugin store",
|
|
656
715
|
featurePinnedCollapse: "Collapsible Pinned section",
|
|
657
716
|
featurePinnedCollapseDesc: 'The sidebar "Pinned" header collapses/expands its task list (like Projects and Groups); the state is remembered.',
|
|
717
|
+
featureSandboxReclaim: "Plugin card sandbox reclaim",
|
|
718
|
+
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).",
|
|
719
|
+
featurePluginCardRetry: "Plugin card auto-retry",
|
|
720
|
+
featurePluginCardRetryDesc: 'Auto-clicks "Reload" on cards that failed the slot cap; they recover as soon as a slot frees up.',
|
|
721
|
+
visionCardUi: "Vision cards",
|
|
658
722
|
pinnedToggleAria: "Collapse/expand Pinned",
|
|
659
723
|
sidebarProjectSpacingName: "Project spacing",
|
|
660
724
|
sidebarProjectSpacingDesc: "Visual spacing between adjacent project rows in the sidebar (row padding included); when set, section gaps (Pinned/Projects/Tasks) follow the same value.",
|
|
@@ -675,6 +739,38 @@
|
|
|
675
739
|
switcherUnseen: "unseen",
|
|
676
740
|
switcherAttentionHint: "Running / finished but unseen tasks \xB7 {prev} / {next} or \u2191 / \u2193 to choose, Enter or release alt to switch",
|
|
677
741
|
switcherAttentionEmpty: "No running or unseen tasks",
|
|
742
|
+
featureNewtabPanels: "Plugin panels on the new tab page",
|
|
743
|
+
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
|
+
ntpDescSuffix: "plugin panel",
|
|
745
|
+
ntpNeedSession: "Open a task session first, then open plugin panels from the new tab page",
|
|
746
|
+
featureStatusBar: "Status bar statistics",
|
|
747
|
+
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
|
+
tabStylesPane: "Styles",
|
|
749
|
+
tabStatusPane: "Status bar",
|
|
750
|
+
sbItemCtx: "Context usage",
|
|
751
|
+
sbItemQuestions: "Questions asked",
|
|
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
|
+
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
|
+
turnUsageTitle: "Turn tokens",
|
|
761
|
+
sbLabelQuestions: "asks",
|
|
762
|
+
sbItemTodayTokens: "Today tokens",
|
|
763
|
+
sbItemTasks: "Tasks",
|
|
764
|
+
sbLabelCtx: "ctx",
|
|
765
|
+
sbLabelTurns: "calls",
|
|
766
|
+
sbLabelToday: "today",
|
|
767
|
+
sbLabelTasks: "tasks",
|
|
768
|
+
sbItemTotalTokens: "Total tokens",
|
|
769
|
+
sbLabelTotal: "total",
|
|
770
|
+
sbMoveUp: "Up",
|
|
771
|
+
sbMoveDown: "Down",
|
|
772
|
+
sbVisible: "shown",
|
|
773
|
+
sbHidden: "hidden",
|
|
678
774
|
tabShortcuts: "Shortcuts",
|
|
679
775
|
hkTitle: "Session quick switch",
|
|
680
776
|
hkAltZ: "Toggle between the current and the last-used session",
|
|
@@ -1014,20 +1110,20 @@
|
|
|
1014
1110
|
}
|
|
1015
1111
|
}
|
|
1016
1112
|
function observeRadixPopups(onPopup) {
|
|
1017
|
-
const
|
|
1113
|
+
const seen2 = /* @__PURE__ */ new WeakSet();
|
|
1018
1114
|
const check = (node) => {
|
|
1019
1115
|
if (!(node instanceof HTMLElement)) return;
|
|
1020
1116
|
if (node.hasAttribute("data-radix-popper-content-wrapper")) {
|
|
1021
1117
|
requestAnimationFrame(() => {
|
|
1022
1118
|
const content = node.firstElementChild;
|
|
1023
|
-
if (content && !
|
|
1024
|
-
|
|
1119
|
+
if (content && !seen2.has(content)) {
|
|
1120
|
+
seen2.add(content);
|
|
1025
1121
|
onPopup(content);
|
|
1026
1122
|
}
|
|
1027
1123
|
});
|
|
1028
1124
|
}
|
|
1029
|
-
if (node.getAttribute && node.getAttribute("role") === "menu" && !
|
|
1030
|
-
|
|
1125
|
+
if (node.getAttribute && node.getAttribute("role") === "menu" && !seen2.has(node)) {
|
|
1126
|
+
seen2.add(node);
|
|
1031
1127
|
requestAnimationFrame(() => {
|
|
1032
1128
|
if (node.isConnected) onPopup(node);
|
|
1033
1129
|
});
|
|
@@ -1687,6 +1783,56 @@
|
|
|
1687
1783
|
text-align: center;
|
|
1688
1784
|
color: var(--color-muted-foreground, #888);
|
|
1689
1785
|
}
|
|
1786
|
+
/* \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
|
|
1787
|
+
\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
|
|
1788
|
+
\u4E0B\u65B9\u662F\u7A97\u5E95\u7559\u767D\u65F6\u8D1F margin \u538B\u5165\u8D34\u5E95\uFF09 */
|
|
1789
|
+
.zcodepro-statusbar {
|
|
1790
|
+
display: flex;
|
|
1791
|
+
justify-content: flex-end;
|
|
1792
|
+
align-items: center;
|
|
1793
|
+
gap: 8px;
|
|
1794
|
+
padding: 7px 14px 0;
|
|
1795
|
+
font-size: 11px;
|
|
1796
|
+
line-height: 1.4;
|
|
1797
|
+
color: var(--color-muted-foreground, #888);
|
|
1798
|
+
user-select: none;
|
|
1799
|
+
pointer-events: none;
|
|
1800
|
+
}
|
|
1801
|
+
.zcodepro-statusbar span[data-tone='warn'] { color: var(--color-amber-500, #f59e0b); }
|
|
1802
|
+
.zcodepro-statusbar span[data-tone='danger'] { color: var(--color-red-500, #ef4444); }
|
|
1803
|
+
.zcodepro-statusbar-sep { opacity: 0.45; }
|
|
1804
|
+
/* \u4F1A\u8BDD\u7EC4\u4E0E\u5168\u5C40\u7EC4\u4E4B\u95F4\u7684\u5206\u754C\u7AD6\u7EBF */
|
|
1805
|
+
.zcodepro-statusbar-groupsep {
|
|
1806
|
+
width: 1px;
|
|
1807
|
+
height: 10px;
|
|
1808
|
+
background: currentColor;
|
|
1809
|
+
opacity: 0.3;
|
|
1810
|
+
margin: 0 2px;
|
|
1811
|
+
}
|
|
1812
|
+
/* \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 */
|
|
1813
|
+
.zcodepro-statusbar span[title] {
|
|
1814
|
+
display: inline-flex;
|
|
1815
|
+
align-items: center;
|
|
1816
|
+
gap: 3px;
|
|
1817
|
+
white-space: nowrap;
|
|
1818
|
+
}
|
|
1819
|
+
.zcodepro-sb-icon {
|
|
1820
|
+
width: 12px;
|
|
1821
|
+
height: 12px;
|
|
1822
|
+
flex-shrink: 0;
|
|
1823
|
+
opacity: 0.6;
|
|
1824
|
+
}
|
|
1825
|
+
.zcodepro-statusbar b { font-weight: 600; color: var(--color-foreground-subtle, #666); }
|
|
1826
|
+
.zcodepro-statusbar i {
|
|
1827
|
+
font-style: normal;
|
|
1828
|
+
opacity: 0.7;
|
|
1829
|
+
font-size: 10px;
|
|
1830
|
+
}
|
|
1831
|
+
/* \u9879\u5185\u77ED\u6807\u7B7E\uFF08\u5982\u201C\u4E0A\u4E0B\u6587\u201D\u201C\u7D2F\u8BA1\u201D\uFF09\uFF0C\u5F31\u5316\u4E0D\u62A2\u6570\u503C */
|
|
1832
|
+
.zcodepro-statusbar em {
|
|
1833
|
+
font-style: normal;
|
|
1834
|
+
opacity: 0.75;
|
|
1835
|
+
}
|
|
1690
1836
|
.zcodepro-switcher-ws {
|
|
1691
1837
|
font-size: 11px;
|
|
1692
1838
|
color: var(--color-muted-foreground, #888);
|
|
@@ -2496,10 +2642,10 @@
|
|
|
2496
2642
|
}
|
|
2497
2643
|
function handleProjectMenu(content) {
|
|
2498
2644
|
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2499
|
-
const
|
|
2645
|
+
const items2 = itemsOf(content);
|
|
2500
2646
|
const newUi = isNewProjectSidebar();
|
|
2501
2647
|
const menuRow = newUi ? openMenuProjectRow() : null;
|
|
2502
|
-
const anchor = newUi ?
|
|
2648
|
+
const anchor = newUi ? items2.find((el) => el.getAttribute("data-testid") === "virtual-project-edit") : items2.find(
|
|
2503
2649
|
(el) => el.hasAttribute("data-testid") && REMOVE_TEXTS.some((x) => itemText(el).startsWith(x))
|
|
2504
2650
|
);
|
|
2505
2651
|
if (!anchor) return;
|
|
@@ -2592,7 +2738,7 @@
|
|
|
2592
2738
|
if (looksLikePath(p2)) return p2;
|
|
2593
2739
|
return pathFromReactFiber(content);
|
|
2594
2740
|
}
|
|
2595
|
-
function appendMenuItem(content, template, anchor, { marker, label, icon, onPick }) {
|
|
2741
|
+
function appendMenuItem(content, template, anchor, { marker, label, icon: icon2, onPick }) {
|
|
2596
2742
|
const item = template.cloneNode(true);
|
|
2597
2743
|
item.removeAttribute("data-testid");
|
|
2598
2744
|
item.removeAttribute("data-highlighted");
|
|
@@ -2601,7 +2747,7 @@
|
|
|
2601
2747
|
item.setAttribute("data-zcodepro-item", marker);
|
|
2602
2748
|
for (const child of [...item.childNodes]) child.remove();
|
|
2603
2749
|
const origIcon = template.querySelector("svg");
|
|
2604
|
-
item.append(buildIcon(origIcon?.getAttribute("class") || "size-4",
|
|
2750
|
+
item.append(buildIcon(origIcon?.getAttribute("class") || "size-4", icon2), document.createTextNode(label));
|
|
2605
2751
|
item.addEventListener("mouseenter", () => {
|
|
2606
2752
|
for (const el of content.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
2607
2753
|
item.setAttribute("data-highlighted", "");
|
|
@@ -2616,8 +2762,8 @@
|
|
|
2616
2762
|
}
|
|
2617
2763
|
function handleFileMenu(content) {
|
|
2618
2764
|
if (content.dataset.zcodeproFileMenu) return;
|
|
2619
|
-
const
|
|
2620
|
-
const copyAbs =
|
|
2765
|
+
const items2 = itemsOf(content);
|
|
2766
|
+
const copyAbs = items2.find((el) => COPY_ABS_TEXTS.some((x) => itemText(el).startsWith(x)));
|
|
2621
2767
|
if (!copyAbs) return;
|
|
2622
2768
|
content.dataset.zcodeproFileMenu = "1";
|
|
2623
2769
|
void (async () => {
|
|
@@ -2632,7 +2778,7 @@
|
|
|
2632
2778
|
}).catch(() => {
|
|
2633
2779
|
});
|
|
2634
2780
|
};
|
|
2635
|
-
const noApps =
|
|
2781
|
+
const noApps = items2.find((el) => NO_APPS_TEXTS.some((x) => itemText(el) === x)) || content.querySelector('[data-disabled][role="menuitem"]');
|
|
2636
2782
|
const openAnchor = noApps && content.contains(noApps) ? noApps : copyAbs;
|
|
2637
2783
|
appendMenuItem(content, copyAbs, openAnchor, {
|
|
2638
2784
|
marker: "file-open-default",
|
|
@@ -2842,10 +2988,10 @@
|
|
|
2842
2988
|
function startImageMenu() {
|
|
2843
2989
|
if (typeof window === "undefined") return;
|
|
2844
2990
|
if (typeof navigator.clipboard?.write !== "function" || typeof window.ClipboardItem === "undefined") return;
|
|
2845
|
-
let
|
|
2991
|
+
let enabled9 = true;
|
|
2846
2992
|
const refresh = () => {
|
|
2847
2993
|
void getConfig().then((c) => {
|
|
2848
|
-
|
|
2994
|
+
enabled9 = !(c.features && c.features.imageCopy === false);
|
|
2849
2995
|
});
|
|
2850
2996
|
};
|
|
2851
2997
|
refresh();
|
|
@@ -2854,7 +3000,7 @@
|
|
|
2854
3000
|
const img = copyTargetOf(e.target, e.clientX, e.clientY);
|
|
2855
3001
|
if (!img) return;
|
|
2856
3002
|
e.preventDefault();
|
|
2857
|
-
if (
|
|
3003
|
+
if (enabled9) showMenu(e.clientX, e.clientY, img);
|
|
2858
3004
|
refresh();
|
|
2859
3005
|
}, true);
|
|
2860
3006
|
}
|
|
@@ -2958,7 +3104,7 @@
|
|
|
2958
3104
|
function waitFor(getter, timeoutMs, step) {
|
|
2959
3105
|
const start = Date.now();
|
|
2960
3106
|
return new Promise((resolve, reject) => {
|
|
2961
|
-
const
|
|
3107
|
+
const tick6 = () => {
|
|
2962
3108
|
let v = null;
|
|
2963
3109
|
try {
|
|
2964
3110
|
v = getter();
|
|
@@ -2972,9 +3118,9 @@
|
|
|
2972
3118
|
reject(new Error(step));
|
|
2973
3119
|
return;
|
|
2974
3120
|
}
|
|
2975
|
-
setTimeout(
|
|
3121
|
+
setTimeout(tick6, 120);
|
|
2976
3122
|
};
|
|
2977
|
-
|
|
3123
|
+
tick6();
|
|
2978
3124
|
});
|
|
2979
3125
|
}
|
|
2980
3126
|
function setReactInputValue(input, value) {
|
|
@@ -3746,7 +3892,7 @@
|
|
|
3746
3892
|
setState(L.upgradeFound.replaceAll("{v}", res.latest || ""));
|
|
3747
3893
|
btn.textContent = L.upgradeNow;
|
|
3748
3894
|
};
|
|
3749
|
-
const
|
|
3895
|
+
const tick6 = async () => {
|
|
3750
3896
|
const res = await rpc(endpoint + "/upgrade");
|
|
3751
3897
|
if (!res.ok) {
|
|
3752
3898
|
stopPoll();
|
|
@@ -3786,9 +3932,9 @@
|
|
|
3786
3932
|
btn.textContent = L.upgradeStop;
|
|
3787
3933
|
setState(L.upgradeRunning);
|
|
3788
3934
|
timer = setInterval(() => {
|
|
3789
|
-
void
|
|
3935
|
+
void tick6();
|
|
3790
3936
|
}, 1500);
|
|
3791
|
-
void
|
|
3937
|
+
void tick6();
|
|
3792
3938
|
};
|
|
3793
3939
|
void (async () => {
|
|
3794
3940
|
const res = await rpc(endpoint + "/upgrade");
|
|
@@ -3997,11 +4143,36 @@
|
|
|
3997
4143
|
if (await setFeature("imageCopy", next)) f.imageCopy = next;
|
|
3998
4144
|
refreshRows();
|
|
3999
4145
|
}),
|
|
4146
|
+
settingRow(L.featureSandboxReclaim, L.featureSandboxReclaimDesc, f.sandboxReclaim !== false, async () => {
|
|
4147
|
+
const next = !(f.sandboxReclaim !== false);
|
|
4148
|
+
if (await setFeature("sandboxReclaim", next)) f.sandboxReclaim = next;
|
|
4149
|
+
refreshRows();
|
|
4150
|
+
}),
|
|
4151
|
+
settingRow(L.featurePluginCardRetry, L.featurePluginCardRetryDesc, f.pluginCardRetry !== false, async () => {
|
|
4152
|
+
const next = !(f.pluginCardRetry !== false);
|
|
4153
|
+
if (await setFeature("pluginCardRetry", next)) f.pluginCardRetry = next;
|
|
4154
|
+
refreshRows();
|
|
4155
|
+
}),
|
|
4000
4156
|
settingRow(L.featureWsRunning, L.featureWsRunningDesc, f.wsRunningSpin !== false, async () => {
|
|
4001
4157
|
const next = !(f.wsRunningSpin !== false);
|
|
4002
4158
|
if (await setFeature("wsRunningSpin", next)) f.wsRunningSpin = next;
|
|
4003
4159
|
refreshRows();
|
|
4004
4160
|
}),
|
|
4161
|
+
settingRow(L.featureNewtabPanels, L.featureNewtabPanelsDesc, f.newtabPanels !== false, async () => {
|
|
4162
|
+
const next = !(f.newtabPanels !== false);
|
|
4163
|
+
if (await setFeature("newtabPanels", next)) f.newtabPanels = next;
|
|
4164
|
+
refreshRows();
|
|
4165
|
+
}),
|
|
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
|
+
}),
|
|
4005
4176
|
(() => {
|
|
4006
4177
|
const repoLink = h("span", {
|
|
4007
4178
|
class: "cursor-pointer underline-offset-4 hover:underline",
|
|
@@ -4034,7 +4205,7 @@
|
|
|
4034
4205
|
const WECHAT_ID = "ai4only";
|
|
4035
4206
|
const ns = "http://www.w3.org/2000/svg";
|
|
4036
4207
|
const extIcon = () => {
|
|
4037
|
-
const
|
|
4208
|
+
const icon2 = h("svg", {
|
|
4038
4209
|
viewBox: "0 0 24 24",
|
|
4039
4210
|
fill: "none",
|
|
4040
4211
|
stroke: "currentColor",
|
|
@@ -4046,11 +4217,11 @@
|
|
|
4046
4217
|
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"]) {
|
|
4047
4218
|
const p2 = document.createElementNS(ns, "path");
|
|
4048
4219
|
p2.setAttribute("d", d);
|
|
4049
|
-
|
|
4220
|
+
icon2.append(p2);
|
|
4050
4221
|
}
|
|
4051
|
-
return
|
|
4222
|
+
return icon2;
|
|
4052
4223
|
};
|
|
4053
|
-
const communityCard = (title, desc,
|
|
4224
|
+
const communityCard = (title, desc, icon2, onClick) => h(
|
|
4054
4225
|
"div",
|
|
4055
4226
|
{
|
|
4056
4227
|
class: "flex cursor-pointer items-center justify-between gap-2 rounded-xl border border-border p-2 transition-colors hover:bg-surface-hover",
|
|
@@ -4062,7 +4233,7 @@
|
|
|
4062
4233
|
h("div", { class: "truncate text-ui-sm font-medium text-foreground" }, title),
|
|
4063
4234
|
h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" }, desc)
|
|
4064
4235
|
),
|
|
4065
|
-
|
|
4236
|
+
icon2()
|
|
4066
4237
|
);
|
|
4067
4238
|
const communityCards = h(
|
|
4068
4239
|
"div",
|
|
@@ -4205,7 +4376,7 @@
|
|
|
4205
4376
|
),
|
|
4206
4377
|
hkCard
|
|
4207
4378
|
);
|
|
4208
|
-
const paneStyles = h("div", { role: "tabpanel", class: "mt-
|
|
4379
|
+
const paneStyles = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
4209
4380
|
const panePerf = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4210
4381
|
const paneAgents = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
4211
4382
|
const paneProxy = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
@@ -4420,7 +4591,162 @@
|
|
|
4420
4591
|
for (const c of fontCells) c.setOptions(list);
|
|
4421
4592
|
})();
|
|
4422
4593
|
renderToolbarSwitch();
|
|
4423
|
-
|
|
4594
|
+
const paneStylesSub1 = h("div", { class: "mt-4" });
|
|
4595
|
+
const paneStylesSub2 = h("div", { class: "mt-4", style: "display:none" });
|
|
4596
|
+
const ITEM_NAMES = {
|
|
4597
|
+
ctx: "sbItemCtx",
|
|
4598
|
+
questions: "sbItemQuestions",
|
|
4599
|
+
todayTokens: "sbItemTodayTokens",
|
|
4600
|
+
totalTokens: "sbItemTotalTokens",
|
|
4601
|
+
tasks: "sbItemTasks"
|
|
4602
|
+
};
|
|
4603
|
+
const sbItems = () => {
|
|
4604
|
+
const saved = config.statusBar && Array.isArray(config.statusBar.items) ? config.statusBar.items : null;
|
|
4605
|
+
if (!saved) return DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
4606
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
4607
|
+
const list = saved.filter((x) => ITEM_NAMES[x.id]).map((x) => ({ on: x.on !== false, id: x.id }));
|
|
4608
|
+
for (const d of DEFAULT_STATUS_ITEMS) if (!byId.has(d.id)) list.push({ ...d });
|
|
4609
|
+
return [
|
|
4610
|
+
...list.filter((x) => STATUS_SESSION_IDS.has(x.id)),
|
|
4611
|
+
...list.filter((x) => STATUS_GLOBAL_IDS.has(x.id))
|
|
4612
|
+
];
|
|
4613
|
+
};
|
|
4614
|
+
let sbSaving = false;
|
|
4615
|
+
const saveSbItems = async (next) => {
|
|
4616
|
+
if (sbSaving) return;
|
|
4617
|
+
sbSaving = true;
|
|
4618
|
+
try {
|
|
4619
|
+
const res = await rpc("/config", { method: "POST", body: { statusBar: { items: next } } });
|
|
4620
|
+
clearConfigCache();
|
|
4621
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4622
|
+
if (!res.ok) {
|
|
4623
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4624
|
+
renderSbItems();
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
if (res.config && res.config.statusBar) config.statusBar = res.config.statusBar;
|
|
4628
|
+
} finally {
|
|
4629
|
+
sbSaving = false;
|
|
4630
|
+
}
|
|
4631
|
+
renderSbItems();
|
|
4632
|
+
};
|
|
4633
|
+
const sbList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4634
|
+
const sbGlobalList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4635
|
+
const TURN_NAMES = { turnIn: "sbLabelIn", turnOut: "sbLabelOut", turnCache: "sbLabelCache" };
|
|
4636
|
+
const turnItems = () => {
|
|
4637
|
+
const saved = config.statusBar && Array.isArray(config.statusBar.turnItems) ? config.statusBar.turnItems : null;
|
|
4638
|
+
if (!saved) return DEFAULT_TURN_ITEMS.map((x) => ({ ...x }));
|
|
4639
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
4640
|
+
const list = saved.filter((x) => TURN_NAMES[x.id]).map((x) => ({ on: x.on !== false, id: x.id }));
|
|
4641
|
+
for (const d of DEFAULT_TURN_ITEMS) if (!byId.has(d.id)) list.push({ ...d });
|
|
4642
|
+
return list;
|
|
4643
|
+
};
|
|
4644
|
+
const saveTurnItems = async (next) => {
|
|
4645
|
+
if (sbSaving) return;
|
|
4646
|
+
sbSaving = true;
|
|
4647
|
+
try {
|
|
4648
|
+
const res = await rpc("/config", { method: "POST", body: { statusBar: { turnItems: next } } });
|
|
4649
|
+
clearConfigCache();
|
|
4650
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4651
|
+
if (!res.ok) {
|
|
4652
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4653
|
+
renderSbItems();
|
|
4654
|
+
return;
|
|
4655
|
+
}
|
|
4656
|
+
if (res.config && res.config.statusBar) config.statusBar = res.config.statusBar;
|
|
4657
|
+
} finally {
|
|
4658
|
+
sbSaving = false;
|
|
4659
|
+
}
|
|
4660
|
+
renderSbItems();
|
|
4661
|
+
};
|
|
4662
|
+
const turnList = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4663
|
+
const renderSbItems = () => {
|
|
4664
|
+
turnList.replaceChildren(...turnItems().map((it, i) => h(
|
|
4665
|
+
"div",
|
|
4666
|
+
{ class: "flex items-center gap-2 px-3 py-2" },
|
|
4667
|
+
h("span", { class: "min-w-0 flex-1 truncate text-ui-sm text-foreground-subtle" }, L[TURN_NAMES[it.id]] || it.id),
|
|
4668
|
+
btnSmall(it.on ? L.sbVisible : L.sbHidden, () => {
|
|
4669
|
+
void saveTurnItems(turnItems().map((x) => x.id === it.id ? { ...x, on: !x.on } : x));
|
|
4670
|
+
}),
|
|
4671
|
+
btnSmall("\u2191", () => {
|
|
4672
|
+
const a = turnItems();
|
|
4673
|
+
if (i > 0) {
|
|
4674
|
+
[a[i - 1], a[i]] = [a[i], a[i - 1]];
|
|
4675
|
+
void saveTurnItems(a);
|
|
4676
|
+
}
|
|
4677
|
+
}),
|
|
4678
|
+
btnSmall("\u2193", () => {
|
|
4679
|
+
const a = turnItems();
|
|
4680
|
+
if (i < a.length - 1) {
|
|
4681
|
+
[a[i], a[i + 1]] = [a[i + 1], a[i]];
|
|
4682
|
+
void saveTurnItems(a);
|
|
4683
|
+
}
|
|
4684
|
+
})
|
|
4685
|
+
)));
|
|
4686
|
+
const list = sbItems();
|
|
4687
|
+
const renderGroup = (el, groupIds) => {
|
|
4688
|
+
const idxs = list.map((x, i) => i).filter((i) => groupIds.has(list[i].id));
|
|
4689
|
+
el.replaceChildren(...idxs.map((i) => {
|
|
4690
|
+
const it = list[i];
|
|
4691
|
+
const swap = (dir) => {
|
|
4692
|
+
const a = sbItems();
|
|
4693
|
+
const same = a.map((x, j) => j).filter((j) => groupIds.has(a[j].id));
|
|
4694
|
+
const pos = same.indexOf(i);
|
|
4695
|
+
const other = same[pos + dir];
|
|
4696
|
+
if (other == null) return;
|
|
4697
|
+
[a[i], a[other]] = [a[other], a[i]];
|
|
4698
|
+
void saveSbItems(a);
|
|
4699
|
+
};
|
|
4700
|
+
return h(
|
|
4701
|
+
"div",
|
|
4702
|
+
{ class: "flex items-center gap-2 px-3 py-2" },
|
|
4703
|
+
h(
|
|
4704
|
+
"span",
|
|
4705
|
+
{ class: "min-w-0 flex-1 truncate text-ui-sm text-foreground-subtle" },
|
|
4706
|
+
L[ITEM_NAMES[it.id]] || it.id
|
|
4707
|
+
),
|
|
4708
|
+
btnSmall(it.on ? L.sbVisible : L.sbHidden, () => {
|
|
4709
|
+
void saveSbItems(sbItems().map((x, j) => j === i ? { ...x, on: !x.on } : x));
|
|
4710
|
+
}),
|
|
4711
|
+
btnSmall("\u2191", () => swap(-1)),
|
|
4712
|
+
btnSmall("\u2193", () => swap(1))
|
|
4713
|
+
);
|
|
4714
|
+
}));
|
|
4715
|
+
};
|
|
4716
|
+
renderGroup(sbList, STATUS_SESSION_IDS);
|
|
4717
|
+
renderGroup(sbGlobalList, STATUS_GLOBAL_IDS);
|
|
4718
|
+
};
|
|
4719
|
+
renderSbItems();
|
|
4720
|
+
paneStylesSub2.append(
|
|
4721
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.featureStatusBarDesc),
|
|
4722
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupSession),
|
|
4723
|
+
sbList,
|
|
4724
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupGlobal),
|
|
4725
|
+
sbGlobalList,
|
|
4726
|
+
h("div", { class: "mt-3 mb-1 text-ui-sm font-medium" }, L.sbGroupTurn),
|
|
4727
|
+
turnList
|
|
4728
|
+
);
|
|
4729
|
+
let stylesSubTab = "styles";
|
|
4730
|
+
const stylesSubTablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist" });
|
|
4731
|
+
const renderStylesSubTabs = () => stylesSubTablist.replaceChildren(...[
|
|
4732
|
+
["styles", L.tabStylesPane],
|
|
4733
|
+
["status", L.tabStatusPane]
|
|
4734
|
+
].map(([id, label]) => h("button", {
|
|
4735
|
+
type: "button",
|
|
4736
|
+
role: "tab",
|
|
4737
|
+
class: "zcodepro-tab",
|
|
4738
|
+
"aria-selected": String(stylesSubTab === id),
|
|
4739
|
+
"data-state": stylesSubTab === id ? "active" : "inactive",
|
|
4740
|
+
onClick: () => {
|
|
4741
|
+
stylesSubTab = id;
|
|
4742
|
+
paneStylesSub1.style.display = id === "styles" ? "" : "none";
|
|
4743
|
+
paneStylesSub2.style.display = id === "status" ? "" : "none";
|
|
4744
|
+
renderStylesSubTabs();
|
|
4745
|
+
}
|
|
4746
|
+
}, label)));
|
|
4747
|
+
renderStylesSubTabs();
|
|
4748
|
+
paneStyles.append(stylesSubTablist, paneStylesSub1, paneStylesSub2);
|
|
4749
|
+
paneStylesSub1.append(
|
|
4424
4750
|
toolbarSwitchWrap,
|
|
4425
4751
|
h(
|
|
4426
4752
|
"div",
|
|
@@ -5418,6 +5744,11 @@
|
|
|
5418
5744
|
h(
|
|
5419
5745
|
"div",
|
|
5420
5746
|
{ class: "ml-auto flex items-center gap-4" },
|
|
5747
|
+
settingRow(L.visionCardUi, "", visionCfg.cardUi !== false, async () => {
|
|
5748
|
+
visionCfg.cardUi = !(visionCfg.cardUi !== false);
|
|
5749
|
+
await persistVision();
|
|
5750
|
+
renderVision();
|
|
5751
|
+
}),
|
|
5421
5752
|
settingRow(L.visionForceIntercept, "", visionCfg.forceIntercept !== false, async () => {
|
|
5422
5753
|
visionCfg.forceIntercept = !(visionCfg.forceIntercept !== false);
|
|
5423
5754
|
await persistVision();
|
|
@@ -6493,11 +6824,11 @@
|
|
|
6493
6824
|
const rootEl = document.getElementById("root");
|
|
6494
6825
|
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6495
6826
|
if (!containerKey) return null;
|
|
6496
|
-
const
|
|
6827
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
6497
6828
|
let found = null;
|
|
6498
6829
|
const scanObj = (o) => {
|
|
6499
|
-
if (!o || typeof o !== "object" ||
|
|
6500
|
-
|
|
6830
|
+
if (!o || typeof o !== "object" || seen2.has(o) || found) return;
|
|
6831
|
+
seen2.add(o);
|
|
6501
6832
|
const ts = o.zcodeTaskService;
|
|
6502
6833
|
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6503
6834
|
};
|
|
@@ -6636,22 +6967,22 @@
|
|
|
6636
6967
|
}, 0);
|
|
6637
6968
|
}
|
|
6638
6969
|
function apply() {
|
|
6639
|
-
const
|
|
6970
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
6640
6971
|
for (const row of document.querySelectorAll(WS_SEL())) {
|
|
6641
6972
|
const path = rowPath(row);
|
|
6642
6973
|
if (!path) continue;
|
|
6643
|
-
|
|
6974
|
+
seen2.add(path);
|
|
6644
6975
|
const head = wsHead(row);
|
|
6645
6976
|
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6646
6977
|
const domRunning = !!(runningByWs.get(path) && runningByWs.get(path).size);
|
|
6647
6978
|
const normP = (v) => String(v || "").replace(/[\\/]+$/, "");
|
|
6648
6979
|
const running = enabled2 && collapsed && (activeProjectPaths.size ? [...activeProjectPaths].some((p2) => normP(p2) === normP(path)) : domRunning);
|
|
6649
|
-
const
|
|
6650
|
-
|
|
6651
|
-
setRunningIcon(
|
|
6980
|
+
const icon2 = iconHolderOf(row);
|
|
6981
|
+
icon2?.classList.toggle("zcodepro-ws-running", running);
|
|
6982
|
+
setRunningIcon(icon2, running);
|
|
6652
6983
|
}
|
|
6653
6984
|
applySectionSpin();
|
|
6654
|
-
for (const ws of [...runningByWs.keys()]) if (!
|
|
6985
|
+
for (const ws of [...runningByWs.keys()]) if (!seen2.has(ws)) runningByWs.delete(ws);
|
|
6655
6986
|
}
|
|
6656
6987
|
var headInfoCache = /* @__PURE__ */ new WeakMap();
|
|
6657
6988
|
var PROJECT_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u9879\u76EE", "projects"]);
|
|
@@ -7417,6 +7748,608 @@
|
|
|
7417
7748
|
window.addEventListener("blur", () => closePopup(false));
|
|
7418
7749
|
}
|
|
7419
7750
|
|
|
7751
|
+
// src/inject/features/newtab-panels.js
|
|
7752
|
+
var GRID_HINTS = ["\u8FD0\u884C\u547D\u4EE4\u548C\u67E5\u770B\u8F93\u51FA", "Run commands and view output"];
|
|
7753
|
+
var OFFICIAL_SUFFIX = "@zcode-plugins-official";
|
|
7754
|
+
var OPEN_FN_MARK = "\u6253\u5F00\u63D2\u4EF6 UI";
|
|
7755
|
+
var enabled3 = true;
|
|
7756
|
+
var injectTimer = 0;
|
|
7757
|
+
function eachFiber(visit) {
|
|
7758
|
+
const rootEl = document.getElementById("root");
|
|
7759
|
+
const key = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
7760
|
+
if (!key) return;
|
|
7761
|
+
let visited = 0;
|
|
7762
|
+
const walk = (f) => {
|
|
7763
|
+
if (!f || visited > 2e5) return;
|
|
7764
|
+
visited++;
|
|
7765
|
+
if (visit(f)) return true;
|
|
7766
|
+
return walk(f.child) || walk(f.sibling);
|
|
7767
|
+
};
|
|
7768
|
+
walk(rootEl[key]);
|
|
7769
|
+
}
|
|
7770
|
+
function findOpenSidePane() {
|
|
7771
|
+
let found = null;
|
|
7772
|
+
eachFiber((f) => {
|
|
7773
|
+
const et = f.elementType;
|
|
7774
|
+
if (et && typeof et === "object" && typeof et.$$typeof === "symbol" && String(et.$$typeof).includes("react.context")) {
|
|
7775
|
+
const val = f.memoizedProps && f.memoizedProps.value;
|
|
7776
|
+
if (typeof val === "function" && val.toString().includes(OPEN_FN_MARK)) {
|
|
7777
|
+
found = val;
|
|
7778
|
+
return true;
|
|
7779
|
+
}
|
|
7780
|
+
}
|
|
7781
|
+
return false;
|
|
7782
|
+
});
|
|
7783
|
+
return found;
|
|
7784
|
+
}
|
|
7785
|
+
function findBridge() {
|
|
7786
|
+
let holder = null;
|
|
7787
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
7788
|
+
const scan5 = (o) => {
|
|
7789
|
+
if (!o || typeof o !== "object" || seen2.has(o) || holder) return;
|
|
7790
|
+
seen2.add(o);
|
|
7791
|
+
if (typeof o.pluginUiBridgeService === "object" && o.pluginUiBridgeService) {
|
|
7792
|
+
holder = o.pluginUiBridgeService;
|
|
7793
|
+
return;
|
|
7794
|
+
}
|
|
7795
|
+
for (const v of Object.values(o)) if (v && typeof v === "object") scan5(v);
|
|
7796
|
+
};
|
|
7797
|
+
eachFiber((f) => {
|
|
7798
|
+
for (const h2 of [f.memoizedProps, f.memoizedState]) {
|
|
7799
|
+
if (!h2 || typeof h2 !== "object") continue;
|
|
7800
|
+
scan5(h2);
|
|
7801
|
+
if (holder) return true;
|
|
7802
|
+
}
|
|
7803
|
+
return false;
|
|
7804
|
+
});
|
|
7805
|
+
return holder;
|
|
7806
|
+
}
|
|
7807
|
+
function sessionScope() {
|
|
7808
|
+
const rows = [...document.querySelectorAll("[data-task-item-key]")];
|
|
7809
|
+
const cur = rows.find((e) => (e.className + "").includes("bg-selected")) || rows[rows.length - 1];
|
|
7810
|
+
const key = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
7811
|
+
if (!key) return null;
|
|
7812
|
+
const i = key.indexOf(":sess_");
|
|
7813
|
+
return i > 0 ? { workspacePath: key.slice(0, i), sessionId: key.slice(i + 1) } : null;
|
|
7814
|
+
}
|
|
7815
|
+
async function thirdPartySurfaces(bridge, workspacePath) {
|
|
7816
|
+
try {
|
|
7817
|
+
const list = await bridge.listSurfaces({ workspacePath });
|
|
7818
|
+
return (list || []).filter((s) => !String(s.pluginId || "").endsWith(OFFICIAL_SUFFIX));
|
|
7819
|
+
} catch {
|
|
7820
|
+
return [];
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7823
|
+
function surfaceTitle(s, locale) {
|
|
7824
|
+
const title = s.title;
|
|
7825
|
+
const pick = (obj) => {
|
|
7826
|
+
const lang = (locale || "").split("-")[0];
|
|
7827
|
+
return obj[locale] || lang && obj[lang] || Object.entries(obj).find(([k]) => k.toLowerCase().startsWith(lang || "\0"))?.[1] || obj.en || Object.values(obj)[0] || "";
|
|
7828
|
+
};
|
|
7829
|
+
if (typeof title === "string") return title;
|
|
7830
|
+
if (title && typeof title === "object") {
|
|
7831
|
+
return pick(title) || s.pluginName || s.id;
|
|
7832
|
+
}
|
|
7833
|
+
return s.pluginName || s.id;
|
|
7834
|
+
}
|
|
7835
|
+
var PANEL_ICON_PATHS = ['<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>'];
|
|
7836
|
+
function findNewTabGrid() {
|
|
7837
|
+
const item = document.querySelector("[data-side-pane-open-tab-item]");
|
|
7838
|
+
if (!item || item.offsetParent === null) return null;
|
|
7839
|
+
const grid = item.parentElement;
|
|
7840
|
+
if (!grid || grid === document.body) return null;
|
|
7841
|
+
const text = grid.textContent || "";
|
|
7842
|
+
return GRID_HINTS.some((h2) => text.includes(h2)) ? grid : null;
|
|
7843
|
+
}
|
|
7844
|
+
async function injectPanels(grid) {
|
|
7845
|
+
if (grid.dataset.zcodeproPanels) return;
|
|
7846
|
+
const template = grid.querySelector("[data-side-pane-open-tab-item]");
|
|
7847
|
+
if (!template) return;
|
|
7848
|
+
const scope = sessionScope();
|
|
7849
|
+
if (!scope) return;
|
|
7850
|
+
const bridge = findBridge();
|
|
7851
|
+
if (!bridge) return;
|
|
7852
|
+
const surfaces = await thirdPartySurfaces(bridge, scope.workspacePath);
|
|
7853
|
+
if (!surfaces.length) {
|
|
7854
|
+
grid.dataset.zcodeproPanels = "1";
|
|
7855
|
+
return;
|
|
7856
|
+
}
|
|
7857
|
+
grid.dataset.zcodeproPanels = "1";
|
|
7858
|
+
const L = t();
|
|
7859
|
+
const locale = isZhLocale() ? "zh-CN" : "en-US";
|
|
7860
|
+
for (const s of surfaces) {
|
|
7861
|
+
const card = template.cloneNode(true);
|
|
7862
|
+
card.removeAttribute("data-side-pane-open-tab-item");
|
|
7863
|
+
card.setAttribute("data-zcodepro-panel", s.id);
|
|
7864
|
+
card.setAttribute("data-zcodepro-panel-name", s.pluginName || "");
|
|
7865
|
+
const title = surfaceTitle(s, locale);
|
|
7866
|
+
const desc = (s.pluginName || "") + " \xB7 " + L.ntpDescSuffix;
|
|
7867
|
+
const titleEl = card.querySelector("span.font-semibold");
|
|
7868
|
+
if (titleEl) titleEl.textContent = title;
|
|
7869
|
+
const descEl = card.querySelector("span[title]");
|
|
7870
|
+
if (descEl) {
|
|
7871
|
+
descEl.textContent = desc;
|
|
7872
|
+
descEl.setAttribute("title", desc);
|
|
7873
|
+
}
|
|
7874
|
+
const svg = card.querySelector("svg");
|
|
7875
|
+
if (svg) {
|
|
7876
|
+
svg.innerHTML = PANEL_ICON_PATHS[0];
|
|
7877
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
7878
|
+
}
|
|
7879
|
+
card.addEventListener("click", (ev) => {
|
|
7880
|
+
ev.stopPropagation();
|
|
7881
|
+
const sc = sessionScope();
|
|
7882
|
+
const open = findOpenSidePane();
|
|
7883
|
+
if (!sc || !open) {
|
|
7884
|
+
showToast(L.ntpNeedSession, "error");
|
|
7885
|
+
return;
|
|
7886
|
+
}
|
|
7887
|
+
try {
|
|
7888
|
+
open({
|
|
7889
|
+
parentSessionId: sc.sessionId,
|
|
7890
|
+
pluginId: s.pluginId,
|
|
7891
|
+
surfaceId: s.id,
|
|
7892
|
+
serverName: s.server,
|
|
7893
|
+
resourceUri: s.resourceUri,
|
|
7894
|
+
remoteSessionId: null,
|
|
7895
|
+
title,
|
|
7896
|
+
workspacePath: sc.workspacePath
|
|
7897
|
+
});
|
|
7898
|
+
} catch (e) {
|
|
7899
|
+
console.warn("[zcodepro] \u6253\u5F00\u63D2\u4EF6\u9762\u677F\u5931\u8D25", e);
|
|
7900
|
+
showToast(L.ntpNeedSession, "error");
|
|
7901
|
+
}
|
|
7902
|
+
});
|
|
7903
|
+
grid.append(card);
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
function tryInject() {
|
|
7907
|
+
if (!enabled3 || document.hidden) return;
|
|
7908
|
+
const grid = findNewTabGrid();
|
|
7909
|
+
if (!grid) return;
|
|
7910
|
+
if (grid.dataset.zcodeproPanels && !grid.querySelector("[data-zcodepro-panel]")) {
|
|
7911
|
+
delete grid.dataset.zcodeproPanels;
|
|
7912
|
+
}
|
|
7913
|
+
void injectPanels(grid);
|
|
7914
|
+
}
|
|
7915
|
+
function startNewtabPanels() {
|
|
7916
|
+
ensureStyle();
|
|
7917
|
+
const refreshEnabled = () => {
|
|
7918
|
+
void getConfig().then((cfg) => {
|
|
7919
|
+
enabled3 = cfg.features ? cfg.features.newtabPanels !== false : true;
|
|
7920
|
+
}).catch(() => {
|
|
7921
|
+
});
|
|
7922
|
+
};
|
|
7923
|
+
refreshEnabled();
|
|
7924
|
+
window.addEventListener("zcodepro:config-changed", refreshEnabled);
|
|
7925
|
+
const observer2 = new MutationObserver(() => {
|
|
7926
|
+
if (injectTimer) return;
|
|
7927
|
+
injectTimer = setTimeout(() => {
|
|
7928
|
+
injectTimer = 0;
|
|
7929
|
+
tryInject();
|
|
7930
|
+
}, 300);
|
|
7931
|
+
});
|
|
7932
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
7933
|
+
setInterval(tryInject, 5e3);
|
|
7934
|
+
}
|
|
7935
|
+
|
|
7936
|
+
// src/inject/features/status-bar.js
|
|
7937
|
+
var enabled4 = true;
|
|
7938
|
+
var items = DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
7939
|
+
var barEl = null;
|
|
7940
|
+
var lastStats = null;
|
|
7941
|
+
function readCtx() {
|
|
7942
|
+
for (const el of document.querySelectorAll("[title], [aria-label]")) {
|
|
7943
|
+
if (el.closest(".zcodepro-statusbar")) continue;
|
|
7944
|
+
const text = el.getAttribute("title") || el.getAttribute("aria-label") || "";
|
|
7945
|
+
if (!/上下文|context/i.test(text)) continue;
|
|
7946
|
+
const m = text.match(/([\d][\d,]*)\s*\/[^0-9]*([\d][\d,]*)/);
|
|
7947
|
+
if (!m) continue;
|
|
7948
|
+
const used = Number(m[1].replace(/,/g, ""));
|
|
7949
|
+
const size = Number(m[2].replace(/,/g, ""));
|
|
7950
|
+
if (used > 0 && size > used) return { used, size };
|
|
7951
|
+
}
|
|
7952
|
+
return null;
|
|
7953
|
+
}
|
|
7954
|
+
var usageSvc = null;
|
|
7955
|
+
var official = null;
|
|
7956
|
+
var officialAt = 0;
|
|
7957
|
+
function eachFiber2(visit) {
|
|
7958
|
+
const rootEl = document.getElementById("root");
|
|
7959
|
+
const key = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
7960
|
+
if (!key) return;
|
|
7961
|
+
let visited = 0;
|
|
7962
|
+
const walk = (f) => {
|
|
7963
|
+
if (!f || visited > 2e5) return false;
|
|
7964
|
+
visited++;
|
|
7965
|
+
if (visit(f)) return true;
|
|
7966
|
+
return walk(f.child) || walk(f.sibling);
|
|
7967
|
+
};
|
|
7968
|
+
walk(rootEl[key]);
|
|
7969
|
+
}
|
|
7970
|
+
function findUsageService() {
|
|
7971
|
+
let found = null;
|
|
7972
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
7973
|
+
const scan5 = (o) => {
|
|
7974
|
+
if (!o || typeof o !== "object" || seen2.has(o) || found) return;
|
|
7975
|
+
seen2.add(o);
|
|
7976
|
+
if (typeof o.usageStatsService === "object" && o.usageStatsService) {
|
|
7977
|
+
found = o.usageStatsService;
|
|
7978
|
+
return;
|
|
7979
|
+
}
|
|
7980
|
+
for (const v of Object.values(o)) if (v && typeof v === "object") scan5(v);
|
|
7981
|
+
};
|
|
7982
|
+
eachFiber2((f) => {
|
|
7983
|
+
for (const h2 of [f.memoizedProps, f.memoizedState]) {
|
|
7984
|
+
if (!h2 || typeof h2 !== "object") continue;
|
|
7985
|
+
scan5(h2);
|
|
7986
|
+
if (found) return true;
|
|
7987
|
+
}
|
|
7988
|
+
return false;
|
|
7989
|
+
});
|
|
7990
|
+
return found;
|
|
7991
|
+
}
|
|
7992
|
+
function refreshOfficial() {
|
|
7993
|
+
const period = official ? 5 * 6e4 : 3e4;
|
|
7994
|
+
if (Date.now() - officialAt < period) return;
|
|
7995
|
+
officialAt = Date.now();
|
|
7996
|
+
void (async () => {
|
|
7997
|
+
try {
|
|
7998
|
+
if (!usageSvc) usageSvc = findUsageService();
|
|
7999
|
+
if (!usageSvc || typeof usageSvc.getAppUsageSnapshot !== "function") return;
|
|
8000
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
8001
|
+
const [all, d7] = await Promise.all([
|
|
8002
|
+
usageSvc.getAppUsageSnapshot({ range: "all", timeZone }),
|
|
8003
|
+
usageSvc.getAppUsageSnapshot({ range: "7d", timeZone })
|
|
8004
|
+
]);
|
|
8005
|
+
const now = /* @__PURE__ */ new Date();
|
|
8006
|
+
const key = now.getFullYear() + "-" + String(now.getMonth() + 1).padStart(2, "0") + "-" + String(now.getDate()).padStart(2, "0");
|
|
8007
|
+
let todayTokens = 0;
|
|
8008
|
+
const day = (d7 && Array.isArray(d7.dailyModelUsage) ? d7.dailyModelUsage : []).find((d) => d.date === key);
|
|
8009
|
+
if (day) for (const m of day.models || []) todayTokens += Number(m.totalTokens) || 0;
|
|
8010
|
+
official = {
|
|
8011
|
+
todayTokens,
|
|
8012
|
+
totalTokens: Number(all && all.summary && all.summary.totalTokens) || 0,
|
|
8013
|
+
totalSessions: Number(all && all.summary && all.summary.totalSessions) || 0
|
|
8014
|
+
};
|
|
8015
|
+
renderBar();
|
|
8016
|
+
} catch {
|
|
8017
|
+
usageSvc = null;
|
|
8018
|
+
}
|
|
8019
|
+
})();
|
|
8020
|
+
}
|
|
8021
|
+
var GLOBAL_GROUP = /* @__PURE__ */ new Set(["todayTokens", "totalTokens", "tasks"]);
|
|
8022
|
+
var SB_ICONS = {
|
|
8023
|
+
ctx: '<path d="M21.21 15.89A10 10 0 1 1 8 2.83"/><path d="M22 12A10 10 0 0 0 12 2v10z"/>',
|
|
8024
|
+
asks: '<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/>',
|
|
8025
|
+
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"/>',
|
|
8026
|
+
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"/>',
|
|
8027
|
+
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"/>',
|
|
8028
|
+
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"/>'
|
|
8029
|
+
};
|
|
8030
|
+
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>`;
|
|
8031
|
+
function fmtTokens(n) {
|
|
8032
|
+
if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
|
|
8033
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
8034
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
8035
|
+
return String(n);
|
|
8036
|
+
}
|
|
8037
|
+
function fmtNum(n) {
|
|
8038
|
+
if (!isZhLocale()) return fmtTokens(n);
|
|
8039
|
+
if (n < 1e4) return String(n);
|
|
8040
|
+
if (n >= 1e8) {
|
|
8041
|
+
const yi = Math.round(n / 1e8 * 10) / 10;
|
|
8042
|
+
return (yi % 1 === 0 ? String(yi) : yi.toFixed(1)) + "\u4EBF";
|
|
8043
|
+
}
|
|
8044
|
+
const wan = Math.round(n / 1e4 * 10) / 10;
|
|
8045
|
+
return (wan % 1 === 0 ? String(wan) : wan.toFixed(1)) + "\u4E07";
|
|
8046
|
+
}
|
|
8047
|
+
function itemContent(id, L) {
|
|
8048
|
+
const g = lastStats && lastStats.global;
|
|
8049
|
+
const label = (text) => `<em>${text}</em>`;
|
|
8050
|
+
switch (id) {
|
|
8051
|
+
case "ctx": {
|
|
8052
|
+
const dom = readCtx();
|
|
8053
|
+
if (dom) {
|
|
8054
|
+
const pct = Math.round(dom.used / dom.size * 1e3) / 10;
|
|
8055
|
+
const tone = pct >= 95 ? "danger" : pct >= 80 ? "warn" : "";
|
|
8056
|
+
return {
|
|
8057
|
+
html: sbIcon("ctx") + label(L.sbLabelCtx) + `<b>${fmtNum(dom.used)}/${fmtNum(dom.size)}${isZhLocale() ? "\uFF08" : "("}${pct}%${isZhLocale() ? "\uFF09" : ")"}</b>`,
|
|
8058
|
+
title: `${L.sbItemCtx}\uFF1A${dom.used.toLocaleString()} / ${dom.size.toLocaleString()}`,
|
|
8059
|
+
tone
|
|
8060
|
+
};
|
|
8061
|
+
}
|
|
8062
|
+
return null;
|
|
8063
|
+
}
|
|
8064
|
+
case "questions": {
|
|
8065
|
+
const nav = document.querySelector('[data-testid="v4-turn-navigator"]');
|
|
8066
|
+
const n = nav ? Number(nav.getAttribute("data-item-count")) : 0;
|
|
8067
|
+
return n > 0 ? { html: sbIcon("asks") + label(L.sbLabelQuestions) + String(n), title: L.sbItemQuestions } : null;
|
|
8068
|
+
}
|
|
8069
|
+
case "todayTokens": {
|
|
8070
|
+
const n = official ? official.todayTokens : g ? g.todayTokens : 0;
|
|
8071
|
+
return n > 0 ? { html: sbIcon("today") + label(L.sbLabelToday) + fmtNum(n), title: L.sbItemTodayTokens } : null;
|
|
8072
|
+
}
|
|
8073
|
+
case "totalTokens": {
|
|
8074
|
+
const n = official ? official.totalTokens : g ? g.totalTokens : 0;
|
|
8075
|
+
return n > 0 ? { html: sbIcon("total") + label(L.sbLabelTotal) + fmtNum(n), title: L.sbItemTotalTokens } : null;
|
|
8076
|
+
}
|
|
8077
|
+
case "tasks": {
|
|
8078
|
+
const n = official ? official.totalSessions : g ? g.tasks : 0;
|
|
8079
|
+
return n > 0 ? { html: sbIcon("tasks") + label(L.sbLabelTasks) + String(n), title: L.sbItemTasks } : null;
|
|
8080
|
+
}
|
|
8081
|
+
default:
|
|
8082
|
+
return null;
|
|
8083
|
+
}
|
|
8084
|
+
}
|
|
8085
|
+
function renderBar() {
|
|
8086
|
+
const ta = document.querySelector("textarea, [contenteditable=true]");
|
|
8087
|
+
const host = ta && (ta.closest("form") || ta.parentElement);
|
|
8088
|
+
if (!enabled4 || !host || !host.parentElement) {
|
|
8089
|
+
if (barEl) barEl.remove();
|
|
8090
|
+
barEl = null;
|
|
8091
|
+
return;
|
|
8092
|
+
}
|
|
8093
|
+
if (!barEl || !barEl.isConnected) {
|
|
8094
|
+
if (!barEl) {
|
|
8095
|
+
barEl = document.createElement("div");
|
|
8096
|
+
barEl.className = "zcodepro-statusbar";
|
|
8097
|
+
}
|
|
8098
|
+
host.parentElement.insertBefore(barEl, host.nextSibling);
|
|
8099
|
+
}
|
|
8100
|
+
const hasSession = !![...document.querySelectorAll("[data-task-item-key]")].find((e) => (e.className + "").includes("bg-selected"));
|
|
8101
|
+
barEl.style.marginBottom = hasSession ? "-14px" : "0";
|
|
8102
|
+
barEl.style.paddingBottom = hasSession ? "0" : "7px";
|
|
8103
|
+
const L = t();
|
|
8104
|
+
const parts = [];
|
|
8105
|
+
let lastGroup = "";
|
|
8106
|
+
for (const it of items) {
|
|
8107
|
+
if (!it.on) continue;
|
|
8108
|
+
const c = itemContent(it.id, L);
|
|
8109
|
+
if (!c) continue;
|
|
8110
|
+
const group = GLOBAL_GROUP.has(it.id) ? "g" : "s";
|
|
8111
|
+
if (lastGroup && group !== lastGroup) parts.push('<span class="zcodepro-statusbar-groupsep"></span>');
|
|
8112
|
+
lastGroup = group;
|
|
8113
|
+
parts.push(`<span title="${c.title.replace(/"/g, """)}"${c.tone ? ` data-tone="${c.tone}"` : ""}>${c.html}</span>`);
|
|
8114
|
+
}
|
|
8115
|
+
const SEP = '<span class="zcodepro-statusbar-sep">\xB7</span>';
|
|
8116
|
+
const GROUPSEP = '<span class="zcodepro-statusbar-groupsep"></span>';
|
|
8117
|
+
barEl.innerHTML = parts.reduce((acc, p, i) => {
|
|
8118
|
+
if (i === 0) return p;
|
|
8119
|
+
if (p === GROUPSEP || parts[i - 1] === GROUPSEP) return acc + p;
|
|
8120
|
+
return acc + SEP + p;
|
|
8121
|
+
}, "");
|
|
8122
|
+
barEl.style.display = parts.length ? "" : "none";
|
|
8123
|
+
}
|
|
8124
|
+
async function tick() {
|
|
8125
|
+
if (!enabled4 || document.hidden) return;
|
|
8126
|
+
refreshOfficial();
|
|
8127
|
+
const res = await rpc("/stats/usage").catch(() => null);
|
|
8128
|
+
if (res && res.ok) lastStats = res;
|
|
8129
|
+
renderBar();
|
|
8130
|
+
}
|
|
8131
|
+
function startStatusBar() {
|
|
8132
|
+
ensureStyle();
|
|
8133
|
+
const refreshCfg = () => {
|
|
8134
|
+
void getConfig().then((cfg) => {
|
|
8135
|
+
enabled4 = cfg.features ? cfg.features.statusBar !== false : true;
|
|
8136
|
+
const saved = cfg.statusBar && Array.isArray(cfg.statusBar.items) ? cfg.statusBar.items : null;
|
|
8137
|
+
if (saved) {
|
|
8138
|
+
const byId = new Map(saved.map((x) => [x.id, x]));
|
|
8139
|
+
const list = saved.filter((x) => DEFAULT_STATUS_ITEMS.some((d) => d.id === x.id)).map((x) => ({ ...x }));
|
|
8140
|
+
const known = new Set(list.map((x) => x.id));
|
|
8141
|
+
for (const d of DEFAULT_STATUS_ITEMS) {
|
|
8142
|
+
if (!known.has(d.id)) list.push({ ...d });
|
|
8143
|
+
}
|
|
8144
|
+
items = [
|
|
8145
|
+
...list.filter((x) => !GLOBAL_GROUP.has(x.id)),
|
|
8146
|
+
...list.filter((x) => GLOBAL_GROUP.has(x.id))
|
|
8147
|
+
];
|
|
8148
|
+
} else {
|
|
8149
|
+
items = DEFAULT_STATUS_ITEMS.map((x) => ({ ...x }));
|
|
8150
|
+
}
|
|
8151
|
+
renderBar();
|
|
8152
|
+
}).catch(() => {
|
|
8153
|
+
});
|
|
8154
|
+
};
|
|
8155
|
+
refreshCfg();
|
|
8156
|
+
window.addEventListener("zcodepro:config-changed", refreshCfg);
|
|
8157
|
+
document.addEventListener("visibilitychange", () => {
|
|
8158
|
+
if (!document.hidden) void tick();
|
|
8159
|
+
});
|
|
8160
|
+
setInterval(() => {
|
|
8161
|
+
void tick();
|
|
8162
|
+
}, 2e3);
|
|
8163
|
+
let rerenderTimer = 0;
|
|
8164
|
+
new MutationObserver(() => {
|
|
8165
|
+
if (rerenderTimer) return;
|
|
8166
|
+
rerenderTimer = setTimeout(() => {
|
|
8167
|
+
rerenderTimer = 0;
|
|
8168
|
+
renderBar();
|
|
8169
|
+
}, 300);
|
|
8170
|
+
}).observe(document.body, { childList: true, subtree: true });
|
|
8171
|
+
}
|
|
8172
|
+
|
|
8173
|
+
// src/inject/features/turn-usage.js
|
|
8174
|
+
var enabled5 = true;
|
|
8175
|
+
var recentTurns = [];
|
|
8176
|
+
var scanTimer = 0;
|
|
8177
|
+
var turnCfg = [
|
|
8178
|
+
{ id: "turnIn", on: true },
|
|
8179
|
+
{ id: "turnOut", on: true },
|
|
8180
|
+
{ id: "turnCache", on: true }
|
|
8181
|
+
];
|
|
8182
|
+
var refreshTurnItems = () => {
|
|
8183
|
+
void getConfig().then((cfg) => {
|
|
8184
|
+
const saved = cfg.statusBar && Array.isArray(cfg.statusBar.turnItems) ? cfg.statusBar.turnItems : null;
|
|
8185
|
+
if (!saved) return;
|
|
8186
|
+
const known = new Set(turnCfg.map((x) => x.id));
|
|
8187
|
+
const list = saved.filter((x) => x && known.has(x.id)).map((x) => ({ id: x.id, on: x.on !== false }));
|
|
8188
|
+
for (const d of turnCfg) if (!list.some((x) => x.id === d.id)) list.push({ ...d });
|
|
8189
|
+
turnCfg = list;
|
|
8190
|
+
}).catch(() => {
|
|
8191
|
+
});
|
|
8192
|
+
};
|
|
8193
|
+
var ICONS = {
|
|
8194
|
+
up: '<path d="m5 12 7-7 7 7"/><path d="M12 19V5"/>',
|
|
8195
|
+
down: '<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>',
|
|
8196
|
+
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"/>'
|
|
8197
|
+
};
|
|
8198
|
+
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>`;
|
|
8199
|
+
function fmt(n) {
|
|
8200
|
+
if (!isZhLocale()) {
|
|
8201
|
+
if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
|
|
8202
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
8203
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
8204
|
+
return String(n);
|
|
8205
|
+
}
|
|
8206
|
+
if (n >= 1e8) return (n / 1e8).toFixed(1) + "\u4EBF";
|
|
8207
|
+
if (n >= 1e4) {
|
|
8208
|
+
const wan = Math.round(n / 1e4 * 10) / 10;
|
|
8209
|
+
return (wan % 1 === 0 ? String(wan) : wan.toFixed(1)) + "\u4E07";
|
|
8210
|
+
}
|
|
8211
|
+
return String(n);
|
|
8212
|
+
}
|
|
8213
|
+
function findRows() {
|
|
8214
|
+
const rows = [];
|
|
8215
|
+
for (const btn of document.querySelectorAll('[data-testid^="v4-copy-"]')) {
|
|
8216
|
+
const row = btn.parentElement;
|
|
8217
|
+
if (!row || row.dataset.zcodeproTurn) continue;
|
|
8218
|
+
if (!row.querySelector('[data-testid^="v4-feedback-"]')) continue;
|
|
8219
|
+
const timeEl = [...row.querySelectorAll("span")].find((s) => /\d{1,2}:\d{2}$/.test((s.textContent || "").trim()));
|
|
8220
|
+
if (timeEl) {
|
|
8221
|
+
const ts = rowTimeTs((timeEl.textContent || "").trim());
|
|
8222
|
+
if (ts != null) rows.push({ row, ts });
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
return rows;
|
|
8226
|
+
}
|
|
8227
|
+
function currentSessionId() {
|
|
8228
|
+
const rows = [...document.querySelectorAll("[data-task-item-key]")];
|
|
8229
|
+
const cur = rows.find((e) => (e.className + "").includes("bg-selected")) || rows[rows.length - 1];
|
|
8230
|
+
const key = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
8231
|
+
const i = key.lastIndexOf(":sess");
|
|
8232
|
+
return i > 0 ? key.slice(i + 1) : "";
|
|
8233
|
+
}
|
|
8234
|
+
function injectRow(row, bucket) {
|
|
8235
|
+
row.dataset.zcodeproTurn = "1";
|
|
8236
|
+
if (!bucket || bucket.in + bucket.out <= 0) return;
|
|
8237
|
+
const L = t();
|
|
8238
|
+
const el = document.createElement("span");
|
|
8239
|
+
el.dataset.zcodeproTurnSpan = "1";
|
|
8240
|
+
el.className = "select-none text-ui-sm text-foreground-subtlest";
|
|
8241
|
+
el.style.whiteSpace = "nowrap";
|
|
8242
|
+
el.style.display = "inline-flex";
|
|
8243
|
+
el.style.alignItems = "center";
|
|
8244
|
+
el.style.gap = "4px";
|
|
8245
|
+
el.style.marginLeft = "10px";
|
|
8246
|
+
const cachePct = bucket.in > 0 && bucket.cacheRead > 0 ? (bucket.cacheRead / bucket.in * 100).toFixed(2) : "";
|
|
8247
|
+
const group = (html) => `<span style="display:inline-flex;align-items:center;gap:2px">${html}</span>`;
|
|
8248
|
+
const em = (text) => `<em style="font-style:normal;opacity:.75">${text}</em>`;
|
|
8249
|
+
const DOT = '<span style="opacity:.45">\xB7</span>';
|
|
8250
|
+
const sections = [];
|
|
8251
|
+
for (const s of turnCfg) {
|
|
8252
|
+
if (!s.on) continue;
|
|
8253
|
+
if (s.id === "turnIn") sections.push(group(icon("up") + em(L.sbLabelIn) + fmt(bucket.in)));
|
|
8254
|
+
else if (s.id === "turnOut") sections.push(group(icon("down") + em(L.sbLabelOut) + fmt(bucket.out)));
|
|
8255
|
+
else if (s.id === "turnCache" && cachePct) sections.push(group(icon("cache") + em(L.sbLabelCache) + cachePct + "%"));
|
|
8256
|
+
}
|
|
8257
|
+
if (!sections.length) {
|
|
8258
|
+
delete row.dataset.zcodeproTurn;
|
|
8259
|
+
el.remove();
|
|
8260
|
+
return;
|
|
8261
|
+
}
|
|
8262
|
+
const VBAR = '<span style="display:inline-block;width:1px;height:10px;background:currentColor;opacity:.3;margin:0 5px"></span>';
|
|
8263
|
+
el.innerHTML = VBAR + sections.join(DOT);
|
|
8264
|
+
el.title = `${L.turnUsageTitle}\uFF1A${L.sbLabelIn} ${bucket.in.toLocaleString()} / ${L.sbLabelOut} ${bucket.out.toLocaleString()}` + (bucket.cacheRead > 0 ? ` / ${L.sbLabelCache} ${bucket.cacheRead.toLocaleString()}` : "");
|
|
8265
|
+
row.append(el);
|
|
8266
|
+
}
|
|
8267
|
+
function rowTimeTs(text) {
|
|
8268
|
+
const now = /* @__PURE__ */ new Date();
|
|
8269
|
+
let m = text.match(/^(\d{1,2}):(\d{2})$/);
|
|
8270
|
+
if (m) return new Date(now.getFullYear(), now.getMonth(), now.getDate(), +m[1], +m[2]).getTime();
|
|
8271
|
+
m = text.match(/^昨天\s*(\d{1,2}):(\d{2})$/);
|
|
8272
|
+
if (m) {
|
|
8273
|
+
const y = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
8274
|
+
return new Date(y.getFullYear(), y.getMonth(), y.getDate(), +m[1], +m[2]).getTime();
|
|
8275
|
+
}
|
|
8276
|
+
m = text.match(/^(\d{1,2})\/(\d{1,2})\s*(\d{1,2}):(\d{2})$/);
|
|
8277
|
+
if (m) return new Date(now.getFullYear(), +m[1] - 1, +m[2], +m[3], +m[4]).getTime();
|
|
8278
|
+
return null;
|
|
8279
|
+
}
|
|
8280
|
+
var lastSid = "";
|
|
8281
|
+
function scan3() {
|
|
8282
|
+
if (!enabled5) return;
|
|
8283
|
+
const sid = currentSessionId();
|
|
8284
|
+
if (sid !== lastSid) {
|
|
8285
|
+
lastSid = sid;
|
|
8286
|
+
recentTurns = [];
|
|
8287
|
+
void tick2();
|
|
8288
|
+
}
|
|
8289
|
+
for (const el of document.querySelectorAll('[data-zcodepro-turn-span], span[title^="\u672C\u8F6E"], span[title^="Turn"]')) el.remove();
|
|
8290
|
+
for (const row of document.querySelectorAll("[data-zcodepro-turn]")) delete row.dataset.zcodeproTurn;
|
|
8291
|
+
if (document.hidden || !recentTurns.length) return;
|
|
8292
|
+
const rows = findRows().sort((a, b) => a.ts - b.ts);
|
|
8293
|
+
if (!rows.length) return;
|
|
8294
|
+
const agg = rows.map(() => ({ in: 0, out: 0, cacheRead: 0 }));
|
|
8295
|
+
const dayOf = (t2) => {
|
|
8296
|
+
const d = new Date(t2);
|
|
8297
|
+
return d.getFullYear() * 1e4 + (d.getMonth() + 1) * 100 + d.getDate();
|
|
8298
|
+
};
|
|
8299
|
+
for (const b of recentTurns) {
|
|
8300
|
+
let owner = -1;
|
|
8301
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8302
|
+
if (rows[i].ts <= b.ts) owner = i;
|
|
8303
|
+
else break;
|
|
8304
|
+
}
|
|
8305
|
+
if (owner < 0) continue;
|
|
8306
|
+
if (dayOf(rows[owner].ts) !== dayOf(b.ts)) continue;
|
|
8307
|
+
agg[owner].in += b.in;
|
|
8308
|
+
agg[owner].out += b.out;
|
|
8309
|
+
agg[owner].cacheRead += b.cacheRead;
|
|
8310
|
+
}
|
|
8311
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8312
|
+
if (agg[i].in + agg[i].out > 0) injectRow(rows[i].row, agg[i]);
|
|
8313
|
+
}
|
|
8314
|
+
}
|
|
8315
|
+
async function tick2() {
|
|
8316
|
+
if (!enabled5 || document.hidden) return;
|
|
8317
|
+
const sid = currentSessionId();
|
|
8318
|
+
const res = await rpc("/stats/usage" + (sid ? "?session=" + encodeURIComponent(sid) : "")).catch(() => null);
|
|
8319
|
+
if (res && res.ok && Array.isArray(res.recentTurns)) {
|
|
8320
|
+
recentTurns = res.recentTurns;
|
|
8321
|
+
scan3();
|
|
8322
|
+
}
|
|
8323
|
+
}
|
|
8324
|
+
function startTurnUsage() {
|
|
8325
|
+
void getConfig().then((cfg) => {
|
|
8326
|
+
enabled5 = cfg.features ? cfg.features.turnUsage !== false : true;
|
|
8327
|
+
}).catch(() => {
|
|
8328
|
+
});
|
|
8329
|
+
refreshTurnItems();
|
|
8330
|
+
window.addEventListener("zcodepro:config-changed", () => {
|
|
8331
|
+
void getConfig().then((cfg) => {
|
|
8332
|
+
enabled5 = cfg.features ? cfg.features.turnUsage !== false : true;
|
|
8333
|
+
}).catch(() => {
|
|
8334
|
+
});
|
|
8335
|
+
refreshTurnItems();
|
|
8336
|
+
});
|
|
8337
|
+
const observer2 = new MutationObserver(() => {
|
|
8338
|
+
if (scanTimer) return;
|
|
8339
|
+
scanTimer = setTimeout(() => {
|
|
8340
|
+
scanTimer = 0;
|
|
8341
|
+
scan3();
|
|
8342
|
+
}, 1200);
|
|
8343
|
+
});
|
|
8344
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
8345
|
+
setInterval(() => {
|
|
8346
|
+
void tick2();
|
|
8347
|
+
}, 5e3);
|
|
8348
|
+
document.addEventListener("visibilitychange", () => {
|
|
8349
|
+
if (!document.hidden) void tick2();
|
|
8350
|
+
});
|
|
8351
|
+
}
|
|
8352
|
+
|
|
7420
8353
|
// src/inject/features/title-lock.js
|
|
7421
8354
|
var TASK_SEL2 = "[data-task-item-key]";
|
|
7422
8355
|
var SCAN_DEBOUNCE_MS3 = 150;
|
|
@@ -7427,7 +8360,7 @@
|
|
|
7427
8360
|
var MAP_REFRESH_MS = 6e4;
|
|
7428
8361
|
var installed3 = false;
|
|
7429
8362
|
var seenRows = /* @__PURE__ */ new WeakSet();
|
|
7430
|
-
var
|
|
8363
|
+
var enabled6 = true;
|
|
7431
8364
|
var pinned = null;
|
|
7432
8365
|
var resolved = false;
|
|
7433
8366
|
var fetching = null;
|
|
@@ -7442,7 +8375,7 @@
|
|
|
7442
8375
|
const t2 = item.querySelector('[class*="truncate"]');
|
|
7443
8376
|
return t2 ? [t2] : [];
|
|
7444
8377
|
}
|
|
7445
|
-
function
|
|
8378
|
+
function findRows2(key) {
|
|
7446
8379
|
return [...document.querySelectorAll(`${TASK_SEL2}[data-task-item-key="${CSS.escape(key)}"]`)];
|
|
7447
8380
|
}
|
|
7448
8381
|
async function fetchPinned() {
|
|
@@ -7451,8 +8384,8 @@
|
|
|
7451
8384
|
const res = await rpc("/pinned-titles");
|
|
7452
8385
|
if (!res || !res.ok) return null;
|
|
7453
8386
|
resolved = true;
|
|
7454
|
-
|
|
7455
|
-
if (!
|
|
8387
|
+
enabled6 = res.enabled !== false;
|
|
8388
|
+
if (!enabled6) {
|
|
7456
8389
|
pinned = null;
|
|
7457
8390
|
return null;
|
|
7458
8391
|
}
|
|
@@ -7467,7 +8400,7 @@
|
|
|
7467
8400
|
}
|
|
7468
8401
|
}
|
|
7469
8402
|
function isMismatch(item) {
|
|
7470
|
-
if (!
|
|
8403
|
+
if (!enabled6 || !pinned) return null;
|
|
7471
8404
|
const key = item.getAttribute("data-task-item-key") || "";
|
|
7472
8405
|
const want = pinned.get(sessIdOf(key));
|
|
7473
8406
|
if (want === void 0) return null;
|
|
@@ -7485,10 +8418,10 @@
|
|
|
7485
8418
|
}
|
|
7486
8419
|
function scheduleEnforce(key, { immediate = false } = {}) {
|
|
7487
8420
|
if (immediate) {
|
|
7488
|
-
if (
|
|
8421
|
+
if (enabled6 && pinned) {
|
|
7489
8422
|
const want = pinned.get(sessIdOf(key));
|
|
7490
8423
|
if (want !== void 0) {
|
|
7491
|
-
for (const item of
|
|
8424
|
+
for (const item of findRows2(key)) {
|
|
7492
8425
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7493
8426
|
}
|
|
7494
8427
|
}
|
|
@@ -7504,7 +8437,7 @@
|
|
|
7504
8437
|
const want = map.get(sessIdOf(key));
|
|
7505
8438
|
if (want === void 0) return;
|
|
7506
8439
|
let wrote = false;
|
|
7507
|
-
for (const item of
|
|
8440
|
+
for (const item of findRows2(key)) {
|
|
7508
8441
|
if (isMismatch(item) !== key) continue;
|
|
7509
8442
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7510
8443
|
wrote = true;
|
|
@@ -7520,13 +8453,13 @@
|
|
|
7520
8453
|
if (!map) return;
|
|
7521
8454
|
const want = map.get(sessIdOf(key));
|
|
7522
8455
|
if (want === void 0) return;
|
|
7523
|
-
for (const item of
|
|
8456
|
+
for (const item of findRows2(key)) {
|
|
7524
8457
|
if (isMismatch(item) !== key) continue;
|
|
7525
8458
|
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7526
8459
|
}
|
|
7527
8460
|
}
|
|
7528
|
-
function
|
|
7529
|
-
if (!
|
|
8461
|
+
function scan4() {
|
|
8462
|
+
if (!enabled6 || !pinned || pinned.size === 0) return;
|
|
7530
8463
|
for (const item of document.querySelectorAll(TASK_SEL2)) {
|
|
7531
8464
|
const key = isMismatch(item);
|
|
7532
8465
|
if (!key) {
|
|
@@ -7560,23 +8493,23 @@
|
|
|
7560
8493
|
if (scanDebounce3) return;
|
|
7561
8494
|
scanDebounce3 = setTimeout(() => {
|
|
7562
8495
|
scanDebounce3 = 0;
|
|
7563
|
-
|
|
8496
|
+
scan4();
|
|
7564
8497
|
}, SCAN_DEBOUNCE_MS3);
|
|
7565
8498
|
}
|
|
7566
8499
|
var mapRefreshTimer = 0;
|
|
7567
8500
|
function refreshMapSoon() {
|
|
7568
8501
|
if (mapRefreshTimer) return;
|
|
7569
|
-
const
|
|
8502
|
+
const tick6 = () => {
|
|
7570
8503
|
if (document.hidden) {
|
|
7571
|
-
mapRefreshTimer = setTimeout(
|
|
8504
|
+
mapRefreshTimer = setTimeout(tick6, 1e4);
|
|
7572
8505
|
return;
|
|
7573
8506
|
}
|
|
7574
8507
|
mapRefreshTimer = 0;
|
|
7575
|
-
if (
|
|
7576
|
-
if (m)
|
|
8508
|
+
if (enabled6 && resolved) void fetchPinned().then((m) => {
|
|
8509
|
+
if (m) scan4();
|
|
7577
8510
|
});
|
|
7578
8511
|
};
|
|
7579
|
-
mapRefreshTimer = setTimeout(
|
|
8512
|
+
mapRefreshTimer = setTimeout(tick6, MAP_REFRESH_MS);
|
|
7580
8513
|
}
|
|
7581
8514
|
var editingKey = null;
|
|
7582
8515
|
var bootDelay = 0;
|
|
@@ -7590,16 +8523,16 @@
|
|
|
7590
8523
|
}
|
|
7591
8524
|
async function bootstrap() {
|
|
7592
8525
|
const map = await fetchPinned();
|
|
7593
|
-
if (map)
|
|
8526
|
+
if (map) scan4();
|
|
7594
8527
|
}
|
|
7595
8528
|
function setRowTitle(key, text) {
|
|
7596
|
-
for (const item of
|
|
8529
|
+
for (const item of findRows2(key)) {
|
|
7597
8530
|
for (const el of titleElsOf(item)) writeTitle(el, text);
|
|
7598
8531
|
}
|
|
7599
8532
|
}
|
|
7600
8533
|
function refreshPinnedTitles() {
|
|
7601
8534
|
return fetchPinned().then((m) => {
|
|
7602
|
-
if (m)
|
|
8535
|
+
if (m) scan4();
|
|
7603
8536
|
});
|
|
7604
8537
|
}
|
|
7605
8538
|
var RENAME_CTX_VALID_MS = 15e3;
|
|
@@ -7618,7 +8551,7 @@
|
|
|
7618
8551
|
renameCtx = null;
|
|
7619
8552
|
return;
|
|
7620
8553
|
}
|
|
7621
|
-
if (!
|
|
8554
|
+
if (!enabled6 || !pinned) return;
|
|
7622
8555
|
const want = pinned.get(sessIdOf(renameCtx.key));
|
|
7623
8556
|
if (want === void 0) return;
|
|
7624
8557
|
for (const el of document.querySelectorAll('[role="dialog"] input, [role="dialog"] textarea, [role="dialog"] [contenteditable="true"]')) {
|
|
@@ -7656,10 +8589,10 @@
|
|
|
7656
8589
|
}, true);
|
|
7657
8590
|
scheduleBootRetry();
|
|
7658
8591
|
setInterval(() => {
|
|
7659
|
-
if (!document.hidden)
|
|
8592
|
+
if (!document.hidden) scan4();
|
|
7660
8593
|
}, SCAN_FALLBACK_MS3);
|
|
7661
8594
|
document.addEventListener("visibilitychange", () => {
|
|
7662
|
-
if (!document.hidden)
|
|
8595
|
+
if (!document.hidden) scan4();
|
|
7663
8596
|
});
|
|
7664
8597
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
7665
8598
|
void bootstrap();
|
|
@@ -7675,7 +8608,7 @@
|
|
|
7675
8608
|
if (editingKey === null) return;
|
|
7676
8609
|
editingKey = null;
|
|
7677
8610
|
void fetchPinned().then((m) => {
|
|
7678
|
-
if (m)
|
|
8611
|
+
if (m) scan4();
|
|
7679
8612
|
});
|
|
7680
8613
|
});
|
|
7681
8614
|
}
|
|
@@ -7906,7 +8839,7 @@
|
|
|
7906
8839
|
await reclaim(ws);
|
|
7907
8840
|
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
7908
8841
|
}
|
|
7909
|
-
async function
|
|
8842
|
+
async function tick3() {
|
|
7910
8843
|
const cfg = await getConfig();
|
|
7911
8844
|
if ((cfg.features || {}).idleReclaim === false) {
|
|
7912
8845
|
idleSince.clear();
|
|
@@ -7968,20 +8901,171 @@
|
|
|
7968
8901
|
}
|
|
7969
8902
|
function startIdleReclaim() {
|
|
7970
8903
|
const loop = () => {
|
|
7971
|
-
|
|
8904
|
+
tick3().catch(() => {
|
|
7972
8905
|
});
|
|
7973
8906
|
};
|
|
7974
8907
|
loop();
|
|
7975
8908
|
setInterval(loop, CHECK_MS);
|
|
7976
8909
|
}
|
|
7977
8910
|
|
|
8911
|
+
// src/inject/features/sandbox-reclaim.js
|
|
8912
|
+
var CHECK_MS2 = 3e4;
|
|
8913
|
+
var MIN_BUDGET = 8;
|
|
8914
|
+
var MAX_BUDGET = 64;
|
|
8915
|
+
var RETRY_COOLDOWN_MS = 10 * 6e4;
|
|
8916
|
+
var SEEN_KEY = "zcodepro:sbx-seen";
|
|
8917
|
+
var seen = /* @__PURE__ */ new Map();
|
|
8918
|
+
function loadSeen() {
|
|
8919
|
+
try {
|
|
8920
|
+
const raw = JSON.parse(localStorage.getItem(SEEN_KEY) || "{}");
|
|
8921
|
+
for (const [id, v] of Object.entries(raw)) {
|
|
8922
|
+
if (id && v && Number.isFinite(v.firstSeen)) seen.set(id, { initId: v.initId, firstSeen: v.firstSeen });
|
|
8923
|
+
}
|
|
8924
|
+
} catch {
|
|
8925
|
+
}
|
|
8926
|
+
}
|
|
8927
|
+
var saveSeenTimer = null;
|
|
8928
|
+
function saveSeenSoon() {
|
|
8929
|
+
if (saveSeenTimer) return;
|
|
8930
|
+
saveSeenTimer = setTimeout(() => {
|
|
8931
|
+
saveSeenTimer = null;
|
|
8932
|
+
try {
|
|
8933
|
+
const out = {};
|
|
8934
|
+
for (const [id, v] of seen) out[id] = v;
|
|
8935
|
+
localStorage.setItem(SEEN_KEY, JSON.stringify(out));
|
|
8936
|
+
} catch {
|
|
8937
|
+
}
|
|
8938
|
+
}, 2e3);
|
|
8939
|
+
}
|
|
8940
|
+
var cooldown = /* @__PURE__ */ new Map();
|
|
8941
|
+
var disabledLogged = false;
|
|
8942
|
+
function onPortsMessage(e) {
|
|
8943
|
+
const d = e.data;
|
|
8944
|
+
if (!d || d.type !== "zcode:plugin-sandbox-ports" || typeof d.sandboxId !== "string") return;
|
|
8945
|
+
seen.set(d.sandboxId, { initId: Number(d.initId) || 0, firstSeen: Date.now() });
|
|
8946
|
+
saveSeenSoon();
|
|
8947
|
+
}
|
|
8948
|
+
function extractSandboxId(wv) {
|
|
8949
|
+
const m = /instance\/(sb-[0-9a-f]+)\//.exec(wv.getAttribute("src") || "");
|
|
8950
|
+
return m ? m[1] : null;
|
|
8951
|
+
}
|
|
8952
|
+
function isVisible(wv) {
|
|
8953
|
+
const root = wv.closest("[data-sandbox-page-root]");
|
|
8954
|
+
if (!root) return wv.getClientRects().length > 0;
|
|
8955
|
+
if (!root.getClientRects().length) return false;
|
|
8956
|
+
return Number(getComputedStyle(root).opacity) > 0.5;
|
|
8957
|
+
}
|
|
8958
|
+
async function tick4() {
|
|
8959
|
+
const cfg = await getConfig();
|
|
8960
|
+
if ((cfg.features || {}).sandboxReclaim === false) {
|
|
8961
|
+
seen.clear();
|
|
8962
|
+
return;
|
|
8963
|
+
}
|
|
8964
|
+
const bridge = window.zcodePluginSandbox;
|
|
8965
|
+
if (!bridge || typeof bridge.disposeSandbox !== "function") {
|
|
8966
|
+
if (!disabledLogged) {
|
|
8967
|
+
disabledLogged = true;
|
|
8968
|
+
console.info("[zcodepro] sandbox-reclaim: \u5F53\u524D\u7A97\u53E3\u65E0 zcodePluginSandbox \u6865\uFF0C\u6C99\u7BB1\u56DE\u6536\u8DF3\u8FC7");
|
|
8969
|
+
}
|
|
8970
|
+
return;
|
|
8971
|
+
}
|
|
8972
|
+
let budget = Number(cfg.sandboxReclaimBudget);
|
|
8973
|
+
if (!Number.isFinite(budget)) budget = 60;
|
|
8974
|
+
budget = Math.min(MAX_BUDGET, Math.max(MIN_BUDGET, budget));
|
|
8975
|
+
const now = Date.now();
|
|
8976
|
+
const visible = /* @__PURE__ */ new Set();
|
|
8977
|
+
for (const wv of document.querySelectorAll("webview")) {
|
|
8978
|
+
const id = extractSandboxId(wv);
|
|
8979
|
+
if (id) {
|
|
8980
|
+
if (isVisible(wv)) visible.add(id);
|
|
8981
|
+
if (!seen.has(id)) {
|
|
8982
|
+
seen.set(id, { initId: void 0, firstSeen: now });
|
|
8983
|
+
saveSeenSoon();
|
|
8984
|
+
}
|
|
8985
|
+
}
|
|
8986
|
+
}
|
|
8987
|
+
while (seen.size > budget) {
|
|
8988
|
+
let pool = [...seen.keys()].filter((id2) => (cooldown.get(id2) || 0) <= now && !visible.has(id2));
|
|
8989
|
+
if (!pool.length) pool = [...seen.keys()].filter((id2) => (cooldown.get(id2) || 0) <= now);
|
|
8990
|
+
pool.sort((a, b) => ((seen.get(a) || {}).firstSeen || 0) - ((seen.get(b) || {}).firstSeen || 0));
|
|
8991
|
+
if (!pool.length) break;
|
|
8992
|
+
const id = pool[0];
|
|
8993
|
+
const entry = seen.get(id);
|
|
8994
|
+
try {
|
|
8995
|
+
await bridge.disposeSandbox(id, entry && entry.initId);
|
|
8996
|
+
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" : ""));
|
|
8997
|
+
} catch (err) {
|
|
8998
|
+
console.warn("[zcodepro] sandbox-reclaim: \u91CA\u653E\u5931\u8D25 " + id, err);
|
|
8999
|
+
seen.delete(id);
|
|
9000
|
+
continue;
|
|
9001
|
+
}
|
|
9002
|
+
seen.delete(id);
|
|
9003
|
+
saveSeenSoon();
|
|
9004
|
+
cooldown.set(id, now + RETRY_COOLDOWN_MS);
|
|
9005
|
+
}
|
|
9006
|
+
if (cooldown.size > 256) {
|
|
9007
|
+
for (const [k, v] of cooldown) {
|
|
9008
|
+
if (v <= now) cooldown.delete(k);
|
|
9009
|
+
}
|
|
9010
|
+
}
|
|
9011
|
+
}
|
|
9012
|
+
function startSandboxReclaim() {
|
|
9013
|
+
loadSeen();
|
|
9014
|
+
window.addEventListener("message", onPortsMessage);
|
|
9015
|
+
const loop = () => {
|
|
9016
|
+
tick4().catch(() => {
|
|
9017
|
+
});
|
|
9018
|
+
};
|
|
9019
|
+
loop();
|
|
9020
|
+
setInterval(loop, CHECK_MS2);
|
|
9021
|
+
}
|
|
9022
|
+
|
|
9023
|
+
// src/inject/features/plugin-card-retry.js
|
|
9024
|
+
var SCAN_MS = 15e3;
|
|
9025
|
+
var CLICK_INTERVAL_MS = 3e4;
|
|
9026
|
+
var MARKERS = ["\u63D2\u4EF6\u754C\u9762"];
|
|
9027
|
+
var lastClickAt = 0;
|
|
9028
|
+
function failedRetryButtons() {
|
|
9029
|
+
const out = [];
|
|
9030
|
+
for (const btn of document.querySelectorAll("button")) {
|
|
9031
|
+
if ((btn.textContent || "").trim() !== "\u91CD\u65B0\u52A0\u8F7D") continue;
|
|
9032
|
+
let anc = btn;
|
|
9033
|
+
for (let i = 0; i < 4 && anc.parentElement; i++) {
|
|
9034
|
+
anc = anc.parentElement;
|
|
9035
|
+
const ctx = anc.textContent || "";
|
|
9036
|
+
if (MARKERS.some((m) => ctx.includes(m))) {
|
|
9037
|
+
out.push(btn);
|
|
9038
|
+
break;
|
|
9039
|
+
}
|
|
9040
|
+
}
|
|
9041
|
+
}
|
|
9042
|
+
return out;
|
|
9043
|
+
}
|
|
9044
|
+
async function tick5() {
|
|
9045
|
+
const cfg = await getConfig();
|
|
9046
|
+
if ((cfg.features || {}).pluginCardRetry === false) return;
|
|
9047
|
+
const now = Date.now();
|
|
9048
|
+
if (now - lastClickAt < CLICK_INTERVAL_MS) return;
|
|
9049
|
+
for (const btn of failedRetryButtons()) {
|
|
9050
|
+
lastClickAt = now;
|
|
9051
|
+
btn.click();
|
|
9052
|
+
break;
|
|
9053
|
+
}
|
|
9054
|
+
}
|
|
9055
|
+
function startPluginCardRetry() {
|
|
9056
|
+
setInterval(() => {
|
|
9057
|
+
tick5().catch(() => {
|
|
9058
|
+
});
|
|
9059
|
+
}, SCAN_MS);
|
|
9060
|
+
}
|
|
9061
|
+
|
|
7978
9062
|
// src/inject/features/toolbar-icons.js
|
|
7979
9063
|
var HIDE_CLASS = "zcodepro-tb-hidden";
|
|
7980
9064
|
var SYNC_DEBOUNCE_MS = 150;
|
|
7981
9065
|
var SCAN_FALLBACK_MS5 = 5e3;
|
|
7982
9066
|
var ROW_SEL = "[data-task-item-key]";
|
|
7983
9067
|
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"]';
|
|
7984
|
-
var
|
|
9068
|
+
var enabled7 = true;
|
|
7985
9069
|
var rowEl = null;
|
|
7986
9070
|
var origs = null;
|
|
7987
9071
|
var syncTimer = 0;
|
|
@@ -8089,8 +9173,8 @@
|
|
|
8089
9173
|
}
|
|
8090
9174
|
});
|
|
8091
9175
|
const newBtn = mk("newTask", parts.newTask, "span.truncate", L.tbNewTask);
|
|
8092
|
-
const
|
|
8093
|
-
if (
|
|
9176
|
+
const icon2 = iconOf(parts.newTask);
|
|
9177
|
+
if (icon2) newBtn.append(icon2);
|
|
8094
9178
|
const searchBtn = mk("search", parts.search, "span.truncate", L.tbSearch);
|
|
8095
9179
|
const sIcon = iconOf(parts.search);
|
|
8096
9180
|
if (sIcon) searchBtn.append(sIcon);
|
|
@@ -8124,7 +9208,7 @@
|
|
|
8124
9208
|
return scroll.getBoundingClientRect().width < NARROW_SIDEBAR_PX;
|
|
8125
9209
|
}
|
|
8126
9210
|
function sync() {
|
|
8127
|
-
if (!
|
|
9211
|
+
if (!enabled7) return;
|
|
8128
9212
|
const parts = findParts();
|
|
8129
9213
|
if (!parts) {
|
|
8130
9214
|
if (rowEl) rowEl.style.display = "none";
|
|
@@ -8186,8 +9270,8 @@
|
|
|
8186
9270
|
}
|
|
8187
9271
|
async function refreshConfig2() {
|
|
8188
9272
|
const cfg = await getConfig(true).catch(() => null);
|
|
8189
|
-
|
|
8190
|
-
if (
|
|
9273
|
+
enabled7 = !cfg || !cfg.features || cfg.features.toolbarIcons !== false;
|
|
9274
|
+
if (enabled7) sync();
|
|
8191
9275
|
else teardown();
|
|
8192
9276
|
}
|
|
8193
9277
|
function startToolbarIcons() {
|
|
@@ -8213,7 +9297,7 @@
|
|
|
8213
9297
|
var STORE_KEY = "zcodepro:pinned-collapsed";
|
|
8214
9298
|
var SYNC_DEBOUNCE_MS2 = 300;
|
|
8215
9299
|
var SCAN_FALLBACK_MS6 = 5e3;
|
|
8216
|
-
var
|
|
9300
|
+
var enabled8 = true;
|
|
8217
9301
|
var syncTimer2 = 0;
|
|
8218
9302
|
function findPinnedHeader() {
|
|
8219
9303
|
for (const h3 of document.querySelectorAll("h3")) {
|
|
@@ -8270,7 +9354,7 @@
|
|
|
8270
9354
|
}
|
|
8271
9355
|
h3.classList.add(HEAD_CLASS);
|
|
8272
9356
|
h3.addEventListener("click", () => {
|
|
8273
|
-
if (
|
|
9357
|
+
if (enabled8) toggle();
|
|
8274
9358
|
});
|
|
8275
9359
|
const btn = h("button", {
|
|
8276
9360
|
type: "button",
|
|
@@ -8279,7 +9363,7 @@
|
|
|
8279
9363
|
"aria-expanded": collapsed ? "false" : "true",
|
|
8280
9364
|
onClick: (e) => {
|
|
8281
9365
|
e.stopPropagation();
|
|
8282
|
-
if (
|
|
9366
|
+
if (enabled8) toggle();
|
|
8283
9367
|
}
|
|
8284
9368
|
});
|
|
8285
9369
|
btn.append(chevronSvg());
|
|
@@ -8287,7 +9371,7 @@
|
|
|
8287
9371
|
return true;
|
|
8288
9372
|
}
|
|
8289
9373
|
function sync2() {
|
|
8290
|
-
if (
|
|
9374
|
+
if (enabled8) apply2();
|
|
8291
9375
|
}
|
|
8292
9376
|
function scheduleSync2() {
|
|
8293
9377
|
if (syncTimer2) return;
|
|
@@ -8316,8 +9400,8 @@
|
|
|
8316
9400
|
}
|
|
8317
9401
|
async function refreshConfig3() {
|
|
8318
9402
|
const cfg = await getConfig(true).catch(() => null);
|
|
8319
|
-
|
|
8320
|
-
if (
|
|
9403
|
+
enabled8 = !cfg || !cfg.features || cfg.features.pinnedCollapse !== false;
|
|
9404
|
+
if (enabled8) sync2();
|
|
8321
9405
|
else teardown2();
|
|
8322
9406
|
}
|
|
8323
9407
|
function startPinnedCollapse() {
|
|
@@ -8352,12 +9436,12 @@
|
|
|
8352
9436
|
return;
|
|
8353
9437
|
}
|
|
8354
9438
|
const sig = status.updates.map((u) => `${u.name}:${u.installed}>${u.latest}`).join(",");
|
|
8355
|
-
let
|
|
9439
|
+
let seen2 = "";
|
|
8356
9440
|
try {
|
|
8357
|
-
|
|
9441
|
+
seen2 = window.localStorage.getItem(NOTIFIED_KEY) || "";
|
|
8358
9442
|
} catch {
|
|
8359
9443
|
}
|
|
8360
|
-
if (
|
|
9444
|
+
if (seen2 === sig) return;
|
|
8361
9445
|
try {
|
|
8362
9446
|
window.localStorage.setItem(NOTIFIED_KEY, sig);
|
|
8363
9447
|
} catch {
|
|
@@ -8432,10 +9516,30 @@
|
|
|
8432
9516
|
startIdleReclaim();
|
|
8433
9517
|
} catch {
|
|
8434
9518
|
}
|
|
9519
|
+
try {
|
|
9520
|
+
startSandboxReclaim();
|
|
9521
|
+
} catch {
|
|
9522
|
+
}
|
|
9523
|
+
try {
|
|
9524
|
+
startPluginCardRetry();
|
|
9525
|
+
} catch {
|
|
9526
|
+
}
|
|
8435
9527
|
try {
|
|
8436
9528
|
startToolbarIcons();
|
|
8437
9529
|
} catch {
|
|
8438
9530
|
}
|
|
9531
|
+
try {
|
|
9532
|
+
startNewtabPanels();
|
|
9533
|
+
} catch {
|
|
9534
|
+
}
|
|
9535
|
+
try {
|
|
9536
|
+
startStatusBar();
|
|
9537
|
+
} catch {
|
|
9538
|
+
}
|
|
9539
|
+
try {
|
|
9540
|
+
startTurnUsage();
|
|
9541
|
+
} catch {
|
|
9542
|
+
}
|
|
8439
9543
|
try {
|
|
8440
9544
|
startPinnedCollapse();
|
|
8441
9545
|
} catch {
|