zcode-pro 0.17.1 → 0.18.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 +6 -3
- package/README.md +6 -3
- package/dist/inject.js +795 -105
- package/package.json +1 -1
- package/src/host/helper.mjs +794 -125
- package/src/host/main.mjs +44 -3
- package/src/host/paths.mjs +32 -10
- package/src/host/pickFolder.mjs +48 -3
- package/src/host/setup.mjs +35 -10
- package/src/host/webdav.mjs +128 -12
- package/src/inject/core.js +140 -32
- package/src/inject/features/plugin-updates.js +1 -1
- package/src/inject/features/settings-dialog.js +597 -70
- package/src/inject/features/styles.js +15 -1
- package/src/inject/index.js +12 -2
- package/src/inject/ui.js +3 -2
package/dist/inject.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
// src/inject/core.js
|
|
3
3
|
var BOOT = typeof window !== "undefined" ? window.__ZCODEPRO__ || {} : {};
|
|
4
4
|
var HELPER_URL = BOOT.helperUrl || "http://127.0.0.1:47889";
|
|
5
|
-
|
|
5
|
+
function liveBoot() {
|
|
6
|
+
return typeof window !== "undefined" && window.__ZCODEPRO__ || BOOT;
|
|
7
|
+
}
|
|
6
8
|
function rpc(path, options = {}) {
|
|
7
|
-
|
|
9
|
+
const boot = liveBoot();
|
|
10
|
+
return fetch((boot.helperUrl || HELPER_URL) + path, {
|
|
8
11
|
method: options.method || "GET",
|
|
9
12
|
headers: {
|
|
10
13
|
"Content-Type": "application/json",
|
|
11
|
-
"X-ZCodePro-Token":
|
|
14
|
+
"X-ZCodePro-Token": boot.token || ""
|
|
12
15
|
},
|
|
13
16
|
body: options.body ? JSON.stringify(options.body) : void 0
|
|
14
17
|
}).then((r) => r.json()).catch((err) => ({ ok: false, error: String(err && err.message || err) }));
|
|
@@ -38,16 +41,24 @@
|
|
|
38
41
|
agentsSave: "\u4FDD\u5B58",
|
|
39
42
|
agentsSaved: "\u5168\u5C40\u63D0\u793A\u8BCD\u5DF2\u4FDD\u5B58",
|
|
40
43
|
agentsLoadFailed: "\u8BFB\u53D6\u5168\u5C40\u63D0\u793A\u8BCD\u5931\u8D25",
|
|
41
|
-
proxyDesc: "\u4E3A ZCode Pro \u672C\u5730\u52A9\u624B\u53D1\u8D77\u7684\u7F51\u7EDC\u8BBF\u95EE\u8BBE\u7F6E HTTP \u4EE3\u7406\uFF1A\u63D2\u4EF6\u5E02\u573A\u7684\u66F4\u65B0\u4E0E\u5B89\u88C5\
|
|
44
|
+
proxyDesc: "\u4E3A ZCode Pro \u672C\u5730\u52A9\u624B\u53D1\u8D77\u7684\u7F51\u7EDC\u8BBF\u95EE\u8BBE\u7F6E HTTP \u4EE3\u7406\uFF1A\u63D2\u4EF6\u5E02\u573A\u7684\u66F4\u65B0\u4E0E\u5B89\u88C5\u3001\u63D2\u4EF6\u4F9D\u8D56\u8F6F\u4EF6\u7684\u5B89\u88C5\u4E0E\u5347\u7EA7\u3001WebDAV \u540C\u6B65\u90FD\u53EF\u8D70\u8BE5\u4EE3\u7406\uFF0C\u7528\u4E0B\u65B9\u5F00\u5173\u9009\u62E9\u751F\u6548\u8303\u56F4\u3002\u4E0D\u5F71\u54CD ZCode \u5E94\u7528\u672C\u8EAB\u4E0E\u6A21\u578B\u8BF7\u6C42\uFF0C\u4FDD\u5B58\u540E\u7ACB\u5373\u751F\u6548\u3002",
|
|
42
45
|
proxyPlaceholder: "http://127.0.0.1:7890",
|
|
43
46
|
proxySave: "\u4FDD\u5B58",
|
|
44
47
|
proxySaved: "\u4EE3\u7406\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
|
|
45
48
|
proxyHint: "\u7559\u7A7A\u4FDD\u5B58\u5373\u6E05\u9664\u4EE3\u7406\u3002",
|
|
46
49
|
proxyTest: "\u68C0\u6D4B",
|
|
47
50
|
proxyTesting: "\u68C0\u6D4B\u4E2D\u2026",
|
|
51
|
+
proxyTestEmpty: "\u8BF7\u5148\u8F93\u5165\u4EE3\u7406\u5730\u5740",
|
|
48
52
|
proxyTestFailed: "\u68C0\u6D4B\u5931\u8D25",
|
|
53
|
+
proxyScopePlugins: "\u63D2\u4EF6\u5E02\u573A\u66F4\u65B0",
|
|
54
|
+
proxyScopePluginsDesc: "\u63D2\u4EF6\u5E02\u573A\u7684\u68C0\u67E5\u66F4\u65B0\u3001\u5B89\u88C5\u4E0E\u5378\u8F7D\uFF08zcode CLI \u7684 git \u64CD\u4F5C\uFF09\u8D70\u4EE3\u7406\u3002",
|
|
55
|
+
proxyScopeDeps: "\u63D2\u4EF6\u4F9D\u8D56\u8F6F\u4EF6",
|
|
56
|
+
proxyScopeDepsDesc: "headroom \u4E0E rtk \u7684\u5B89\u88C5\u3001\u68C0\u67E5\u66F4\u65B0\u4E0E\u5347\u7EA7\uFF08pip \u4E0E GitHub \u4E0B\u8F7D\uFF09\u8D70\u4EE3\u7406\u3002",
|
|
57
|
+
proxyScopeSync: "\u540C\u6B65",
|
|
58
|
+
proxyScopeSyncDesc: "WebDAV \u4E0A\u4F20\u4E0E\u4E0B\u8F7D\u8D70\u4EE3\u7406\u3002\u9ED8\u8BA4\u5173\u95ED\uFF1A\u575A\u679C\u4E91\u7B49\u56FD\u5185\u7F51\u76D8\u76F4\u8FDE\u5373\u53EF\uFF0C\u4EE3\u7406\u505C\u4E86\u540C\u6B65\u4F1A\u8DDF\u7740\u5931\u8D25\u3002",
|
|
49
59
|
tabSync: "\u540C\u6B65",
|
|
50
|
-
|
|
60
|
+
tabDebug: "\u8C03\u8BD5",
|
|
61
|
+
syncDesc: "\u624B\u52A8\u628A ZCode Pro \u8BBE\u7F6E\u4E0E\u6A21\u578B\u8BBE\u7F6E\u5907\u4EFD\u5230 WebDAV\uFF0C\u6216\u5728\u65B0\u7535\u8111\u4E0A\u6062\u590D\u3002\u4E24\u9879\u5404\u81EA\u72EC\u7ACB\u6210\u6587\u4EF6\uFF0C\u53EF\u53EA\u4E0A\u4F20\u6216\u53EA\u8986\u76D6\u5176\u4E2D\u4E00\u9879\uFF1B\u6BCF\u6B21\u4E0A\u4F20\u4F1A\u989D\u5916\u4FDD\u7559\u4E00\u4EFD\u5E26\u65F6\u95F4\u6233\u7684\u5386\u53F2\u7248\u672C\uFF0C\u4E0B\u8F7D\u65F6\u4EFB\u9009\u4E00\u4E2A\u7248\u672C\u6062\u590D\uFF1B\u4EC5\u5728\u70B9\u51FB\u6309\u94AE\u65F6\u4F20\u8F93\uFF0C\u4E0D\u505A\u81EA\u52A8\u540C\u6B65\u3002",
|
|
51
62
|
syncUrlPlaceholder: "https://dav.jianguoyun.com/dav/",
|
|
52
63
|
syncDir: "\u4E0A\u4F20\u76EE\u5F55",
|
|
53
64
|
syncDirPlaceholder: "zcode-pro",
|
|
@@ -55,7 +66,7 @@
|
|
|
55
66
|
syncPassword: "\u5BC6\u7801",
|
|
56
67
|
syncSave: "\u4FDD\u5B58",
|
|
57
68
|
syncSaved: "\u540C\u6B65\u914D\u7F6E\u5DF2\u4FDD\u5B58",
|
|
58
|
-
syncFormHint: "\u540C\u6B65\u6587\u4EF6\u5B58\u5230\u201C\u4E0A\u4F20\u76EE\u5F55\u201D\uFF08\u9ED8\u8BA4 zcode-pro\uFF0C\u53EF\u591A\u7EA7\uFF0C\u81EA\u52A8\u521B\u5EFA\uFF09\
|
|
69
|
+
syncFormHint: "\u540C\u6B65\u6587\u4EF6\u5B58\u5230\u201C\u4E0A\u4F20\u76EE\u5F55\u201D\uFF08\u9ED8\u8BA4 zcode-pro\uFF0C\u53EF\u591A\u7EA7\uFF0C\u81EA\u52A8\u521B\u5EFA\uFF09\uFF1Azcodepro.json \u4E0E model.json \u59CB\u7EC8\u662F\u6700\u65B0\u4E00\u7248\uFF0C\u65C1\u8FB9\u53E6\u4FDD\u7559\u5E26\u65F6\u95F4\u6233\u7684\u5386\u53F2\u7248\u672C\u3002",
|
|
59
70
|
syncRecLink: "\u575A\u679C\u4E91 WebDAV",
|
|
60
71
|
syncRecSuffix: "\uFF1A\u767B\u5F55\u4E0E\u5BC6\u7801\u586B\u201C\u5E94\u7528\u5BC6\u7801\u201D\uFF0C\u4E0D\u662F\u8D26\u53F7\u5BC6\u7801\u3002",
|
|
61
72
|
syncIncludeZcp: "ZCode Pro \u8BBE\u7F6E",
|
|
@@ -65,16 +76,44 @@
|
|
|
65
76
|
syncUpload: "\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
66
77
|
syncDownload: "\u4ECE\u4E91\u7AEF\u4E0B\u8F7D",
|
|
67
78
|
syncUploading: "\u4E0A\u4F20\u4E2D\u2026",
|
|
68
|
-
syncDownloading: "\u4E0B\u8F7D\u4E2D\u2026",
|
|
69
79
|
syncUploaded: "\u5DF2\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
70
80
|
syncDownloaded: "\u5DF2\u4ECE\u4E91\u7AEF\u6062\u590D",
|
|
71
81
|
syncLastPush: "\u4E0A\u6B21\u4E0A\u4F20",
|
|
72
82
|
syncLastPull: "\u4E0A\u6B21\u4E0B\u8F7D",
|
|
73
83
|
syncNever: "\u65E0",
|
|
74
84
|
syncConfirmTitle: "\u4ECE\u4E91\u7AEF\u4E0B\u8F7D",
|
|
75
|
-
syncConfirmDesc: "\u5C06\u7528\
|
|
76
|
-
syncConfirmGo: "\u786E\u8BA4\
|
|
85
|
+
syncConfirmDesc: "\u5C06\u7528\u6240\u9009\u6587\u4EF6\u8986\u76D6\u672C\u673A\u5BF9\u5E94\u7684\u4E00\u9879\uFF08\u8986\u76D6\u524D\u4F1A\u5728\u539F\u6587\u4EF6\u65C1\u7559\u4E0B .zcodepro-backup \u5907\u4EFD\uFF09\uFF1B\u672C\u673A\u7684\u540C\u6B65\u914D\u7F6E\u4E0E\u767B\u5F55\u51ED\u636E\u4E0D\u53D7\u5F71\u54CD\u3002\u6A21\u578B\u8BBE\u7F6E\u6062\u590D\u540E\u5EFA\u8BAE\u91CD\u542F ZCode \u751F\u6548\u3002\u786E\u8BA4\u5BFC\u5165\uFF1F",
|
|
86
|
+
syncConfirmGo: "\u786E\u8BA4\u5BFC\u5165",
|
|
87
|
+
syncPickDesc: "\u56FA\u5B9A\u540D\u6587\u4EF6\u59CB\u7EC8\u662F\u6700\u65B0\u4E00\u7248\uFF0C\u5E26\u65F6\u95F4\u6233\u7684\u662F\u6BCF\u6B21\u4E0A\u4F20\u7559\u4E0B\u7684\u5386\u53F2\u7248\u672C\uFF1B\u300C\u5BFC\u5165\u300D\u7528\u6240\u9009\u6587\u4EF6\u8986\u76D6\u672C\u673A\u5BF9\u5E94\u7684\u4E00\u9879\u3002",
|
|
88
|
+
syncVerDeleteLatestNote: "\u6CE8\u610F\uFF1A\u8FD9\u662F\u201C\u6700\u65B0\u201D\u6587\u4EF6\uFF0C\u65E7\u7248 zcode-pro \u7684\u300C\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u300D\u4F9D\u8D56\u5B83\uFF0C\u5220\u9664\u540E\u65E7\u7248\u673A\u5668\u5C06\u65E0\u6CD5\u4E0B\u8F7D\uFF1B\u5E26\u65F6\u95F4\u6233\u7684\u5386\u53F2\u7248\u672C\u4E0D\u53D7\u5F71\u54CD\u3002",
|
|
77
89
|
syncHint: "\u540C\u6B65\u767B\u5F55\u51ED\u636E\u4EC5\u4FDD\u5B58\u5728\u672C\u673A zcodepro.json\uFF1B\u6A21\u578B\u8BBE\u7F6E\u5305\u542B\u81EA\u5B9A\u4E49\u4F9B\u5E94\u5546\u7684 API Key\uFF0C\u53EA\u4F1A\u4E0A\u4F20\u5230\u4F60\u81EA\u5DF1\u7684 WebDAV\u3002",
|
|
90
|
+
syncTest: "\u6D4B\u8BD5",
|
|
91
|
+
syncTesting: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
92
|
+
syncTestEmpty: "\u8BF7\u5148\u586B\u5199 URL",
|
|
93
|
+
syncTestFailed: "\u6D4B\u8BD5\u5931\u8D25",
|
|
94
|
+
syncTestStepConnect: "\u8FDE\u63A5",
|
|
95
|
+
syncTestStepDir: "\u76EE\u5F55",
|
|
96
|
+
syncTestStepList: "\u6587\u4EF6",
|
|
97
|
+
syncTestFilesFound: "\u4E91\u7AEF\u5DF2\u6709 {n} \u4E2A\u5907\u4EFD\u6587\u4EF6",
|
|
98
|
+
syncPickTitle: "\u8BF7\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6",
|
|
99
|
+
syncPickLoading: "\u6B63\u5728\u8BFB\u53D6\u4E91\u7AEF\u6587\u4EF6\u5217\u8868\u2026",
|
|
100
|
+
syncPickEmpty: "\u4E91\u7AEF\u8FD8\u6CA1\u6709\u5907\u4EFD\u6587\u4EF6\uFF0C\u8BF7\u5148\u5728\u5176\u4ED6\u7535\u8111\u4E0A\u4F20",
|
|
101
|
+
syncVerImport: "\u5BFC\u5165",
|
|
102
|
+
syncVerImporting: "\u5BFC\u5165\u4E2D\u2026",
|
|
103
|
+
syncVerDelete: "\u5220\u9664",
|
|
104
|
+
syncVerSave: "\u4FDD\u5B58\u5230\u78C1\u76D8",
|
|
105
|
+
syncVerSaving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
106
|
+
syncVerLatest: "\u6700\u65B0",
|
|
107
|
+
syncVerDeleteTitle: "\u5220\u9664\u4E91\u7AEF\u6587\u4EF6",
|
|
108
|
+
syncVerDeleteDesc: "\u5C06\u5220\u9664\u4E91\u7AEF\u7684\u8FD9\u4EFD\u5907\u4EFD\uFF0C\u4E0D\u53EF\u6062\u590D\uFF1A",
|
|
109
|
+
syncVerDeleted: "\u5DF2\u5220\u9664\u4E91\u7AEF\u5907\u4EFD",
|
|
110
|
+
syncVerSaved: "\u5DF2\u4FDD\u5B58\u5230",
|
|
111
|
+
devMode: "\u5F00\u53D1\u6A21\u5F0F",
|
|
112
|
+
devModeRowDesc: "\u5F00\u542F\u540E\u51FA\u73B0\u300C\u91CD\u8F7D ZCode Pro\u300D\u6309\u94AE\uFF1B\u4E5F\u53EF\u7ED9\u542F\u52A8\u5668\u8BBE\u73AF\u5883\u53D8\u91CF ZCODEPRO_DEV=1 \u542F\u7528\u3002\u6B64\u6807\u7B7E\u9875\u4EC5\u5728\u5F00\u53D1\u6A21\u5F0F\u751F\u6548\u65F6\u663E\u793A\u3002",
|
|
113
|
+
devModeDesc: "\u5F00\u53D1\u8C03\u8BD5\u7528\uFF1A\u6539\u5B8C zcode-pro \u4EE3\u7801\u540E\u4E0D\u5FC5\u91CD\u542F ZCode\uFF0C\u70B9\u300C\u91CD\u8F7D ZCode Pro\u300D\u5373\u53EF\u52A0\u8F7D\u65B0\u4EE3\u7801\u3002\u6D41\u7A0B\u4E3A\u81EA\u52A8\u6784\u5EFA\uFF08\u9700\u5728\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\uFF09\u2192 \u4EE5\u65B0\u8FDB\u7A0B\u91CD\u542F ZCode Pro\uFF08\u672C\u5730\u52A9\u624B\u4E0E\u6CE8\u5165\u811A\u672C\u90FD\u6362\u65B0\uFF09\u2192 \u6240\u6709 ZCode \u7A97\u53E3\u81EA\u52A8\u5237\u65B0\u5E76\u91CD\u65B0\u6CE8\u5165\uFF1BZCode \u672C\u4F53\u4E0E\u5DF2\u6253\u5F00\u7684\u4F1A\u8BDD\u4E0D\u53D7\u5F71\u54CD\u3002",
|
|
114
|
+
devReload: "\u91CD\u8F7D ZCode Pro",
|
|
115
|
+
devReloading: "\u91CD\u8F7D\u4E2D\u2026",
|
|
116
|
+
devReloadDesc: "\u70B9\u51FB\u540E\u7EA6 2-3 \u79D2\u5185\u6240\u6709 ZCode \u7A97\u53E3\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\u5E76\u52A0\u8F7D\u65B0\u811A\u672C\u3002",
|
|
78
117
|
rowGapName: "\u6BB5\u843D\u95F4\u8DDD",
|
|
79
118
|
rowGapDesc: "\u4F1A\u8BDD\u4E2D\u6BB5\u843D\u7B49\u6587\u672C\u5757\u4E4B\u95F4\u7684\u5782\u76F4\u95F4\u8DDD\uFF08\u56DE\u5408\u4E4B\u95F4\u3001\u7B54\u6848\u5185\u90E8\uFF09\u3002",
|
|
80
119
|
listSpacingName: "\u5217\u8868\u4E0A\u4E0B\u8FB9\u8DDD",
|
|
@@ -91,6 +130,8 @@
|
|
|
91
130
|
tableCellPaddingDesc: "\u8868\u683C\u5355\u5143\u683C\u5185\u7684\u7559\u767D\uFF1B\u5DE6\u8F93\u5165\u6846\u4E3A\u4E0A\u4E0B\u3001\u53F3\u4E3A\u5DE6\u53F3\u3002",
|
|
92
131
|
lineHeightName: "\u56DE\u7B54\u884C\u9AD8",
|
|
93
132
|
lineHeightDesc: "\u56DE\u7B54\u6B63\u6587\u7684\u884C\u9AD8\uFF08\u500D\u6570\uFF09\u3002",
|
|
133
|
+
thinkingLineHeightName: "\u601D\u8003\u884C\u9AD8",
|
|
134
|
+
thinkingLineHeightDesc: "\u300C\u5DF2\u5DE5\u4F5C/\u5DE5\u4F5C\u4E2D\u300D\u8FC7\u7A0B\u8BB0\u5F55\uFF08\u8BFB\u53D6/\u7F16\u8F91/\u67E5\u9605/\u7EC8\u7AEF\u6761\u76EE\u4E0E\u601D\u8003\u5185\u5BB9\uFF09\u7684\u884C\u9AD8\uFF08\u500D\u6570\uFF09\u3002",
|
|
94
135
|
userLineHeightName: "\u63D0\u95EE\u884C\u9AD8",
|
|
95
136
|
userLineHeightDesc: "\u63D0\u95EE\u5185\u5BB9\u7684\u884C\u9AD8\uFF08\u500D\u6570\uFF09\u3002",
|
|
96
137
|
contentWidthName: "\u5185\u5BB9\u5BBD\u5EA6",
|
|
@@ -154,7 +195,7 @@
|
|
|
154
195
|
featurePinnedExpand: "\u7F6E\u9876\u4F1A\u8BDD\u4FDD\u6301\u9879\u76EE\u6298\u53E0\uFF08\u5B9E\u9A8C\u6027\uFF09",
|
|
155
196
|
featurePinnedExpandDesc: "\u70B9\u51FB\u6298\u53E0\u9879\u76EE\u7684\u7F6E\u9876\u4F1A\u8BDD\u540E\u5C06\u5176\u4FDD\u6301\u6298\u53E0\u3002\u53D7\u9650\u4E8E\u5E94\u7528\u673A\u5236\uFF0C\u9879\u76EE\u4F1A\u5148\u77ED\u6682\u5C55\u5F00\u518D\u7F29\u8D77\u3002",
|
|
156
197
|
featureAutoUpdatePlugins: "\u81EA\u52A8\u66F4\u65B0 zcode-plugins \u63D2\u4EF6",
|
|
157
|
-
featureAutoUpdatePluginsDesc: "\u542F\u52A8\u65F6\u81EA\u52A8\u68C0\u67E5\u5E76\u66F4\u65B0\u5DF2\u88C5\u7684 zcode-plugins \u63D2\u4EF6\uFF08\
|
|
198
|
+
featureAutoUpdatePluginsDesc: "\u542F\u52A8\u65F6\u81EA\u52A8\u68C0\u67E5\u5E76\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 zcode-plugins \u63D2\u4EF6\uFF08\u53EA\u5347\u7EA7\u4E0D\u5B89\u88C5\uFF0C\u5378\u8F7D\u4E0D\u4F1A\u88AB\u64A4\u9500\uFF09\uFF0C\u66F4\u65B0\u5728\u65B0\u4F1A\u8BDD\u751F\u6548\u3002",
|
|
158
199
|
pluginsUpdateTitle: "\u63D2\u4EF6\u66F4\u65B0 \xB7 zcode-plugins",
|
|
159
200
|
pluginsCheckNow: "\u68C0\u67E5\u5E76\u66F4\u65B0",
|
|
160
201
|
pluginsUpdating: "\u6B63\u5728\u66F4\u65B0\u63D2\u4EF6\u2026",
|
|
@@ -166,7 +207,7 @@
|
|
|
166
207
|
pluginsAutoUpdated: "zcode-plugins \u63D2\u4EF6\u5DF2\u66F4\u65B0",
|
|
167
208
|
tabVision: "Vision",
|
|
168
209
|
visionDesc: "\u4E3B\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\u65F6\uFF08\u5982 glm-5.3\uFF09\uFF0C\u81EA\u52A8\u628A\u6D88\u606F\u91CC\u7684\u56FE\u7247\u4EA4\u7ED9\u4E0B\u9762\u7684\u89C6\u89C9\u6A21\u578B\u8BC6\u522B\uFF0C\u628A\u63CF\u8FF0\u5E26\u7ED9\u4E3B\u6A21\u578B\uFF08zcode-vision \u63D2\u4EF6\uFF1B/vision-* \u547D\u4EE4\u7F16\u8F91\u540C\u4E00\u914D\u7F6E\uFF09\u3002\u6539\u52A8\u81EA\u52A8\u4FDD\u5B58\u3002",
|
|
169
|
-
visionEnabled: "\u542F\u7528
|
|
210
|
+
visionEnabled: "\u542F\u7528",
|
|
170
211
|
visionForceIntercept: "\u4E3B\u6A21\u578B\u80FD\u770B\u56FE\u4E5F\u62E6\u622A",
|
|
171
212
|
visionMode: "\u94FE\u6A21\u5F0F",
|
|
172
213
|
visionModeFallback: "\u4F9D\u6B21\u5C1D\u8BD5",
|
|
@@ -191,21 +232,21 @@
|
|
|
191
232
|
visionResetChainConfirm: "\u5C06\u94FE\u6A21\u5F0F\u4E0E\u4EE3\u7406\u5217\u8868\u6062\u590D\u4E3A\u9ED8\u8BA4\u4E24\u7EA7\uFF08glm-session \u2192 glm-flash\uFF09\uFF0C\u5F53\u524D\u5BF9\u4EE3\u7406\u7684\u4FEE\u6539\u4F1A\u4E22\u5931\u3002\u7EE7\u7EED\uFF1F",
|
|
192
233
|
visionBaseUrl: "\u63A5\u53E3\u5730\u5740 baseUrl",
|
|
193
234
|
visionModel: "\u6A21\u578B",
|
|
194
|
-
visionFormat: "\u683C\u5F0F",
|
|
195
235
|
visionApiKey: "API Key",
|
|
196
236
|
visionApiKeyHint: "\u7559\u7A7A\u81EA\u52A8\u53D6 GLM \u8BA2\u9605 key",
|
|
197
237
|
visionPrompt: "\u8BC6\u522B\u63D0\u793A\u8BCD\uFF08pipeline \u540E\u7EED\u6B65\u53EF\u7528 {prev} \u5F15\u7528\u4E0A\u4E00\u6B65\uFF09",
|
|
198
238
|
visionTest: "\u6D4B\u8BD5",
|
|
199
239
|
visionTesting: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
200
240
|
visionTestFailed: "\u89C6\u89C9\u4EE3\u7406\u6D4B\u8BD5\u5931\u8D25",
|
|
201
|
-
visionTestOutput: "\u6D4B\u8BD5\u8F93\u51FA",
|
|
202
241
|
visionCompressKB: "\u538B\u7F29\u9608\u503C KB",
|
|
203
242
|
visionCompressKBHint: "\u8D85\u8FC7\u8BE5\u5927\u5C0F\u7684\u56FE\u5148\u538B\u7F29\u518D\u8BC6\u522B\uFF08\u6700\u957F\u8FB9 2000\u3001JPEG\uFF09\uFF1B0 = \u4E0D\u538B\u7F29",
|
|
204
243
|
visionLoadFailed: "\u8BFB\u53D6\u89C6\u89C9\u4EE3\u7406\u914D\u7F6E\u5931\u8D25",
|
|
205
244
|
tabRtk: "rtk",
|
|
206
245
|
rtkDesc: "rtk \u63D2\u4EF6\uFF1A\u628A\u5E38\u89C1\u5F00\u53D1\u547D\u4EE4\u7684\u8F93\u51FA\u538B\u7F29 60-90% \u518D\u8FDB\u5165\u4E0A\u4E0B\u6587\uFF08/rtk-* \u547D\u4EE4\u7F16\u8F91\u540C\u4E00\u914D\u7F6E\uFF09\u3002\u6539\u52A8\u81EA\u52A8\u4FDD\u5B58\u5E76\u7ACB\u5373\u751F\u6548\u3002",
|
|
207
|
-
rtkEnabled: "\u542F\u7528
|
|
208
|
-
rtkNotInstalled: "\u672A\u5B89\u88C5 rtk\
|
|
246
|
+
rtkEnabled: "\u542F\u7528",
|
|
247
|
+
rtkNotInstalled: "\u672A\u5B89\u88C5 rtk \u672C\u4F53\uFF1B\u5B89\u88C5\u540E\u4EE5\u4E0B\u8BBE\u7F6E\u751F\u6548\uFF08\u4F1A\u8BDD\u91CC\u6267\u884C /rtk-setup \u4E5F\u53EF\u4EE5\uFF09",
|
|
248
|
+
rtkInstallBin: "\u5B89\u88C5 rtk \u672C\u4F53",
|
|
249
|
+
rtkBinInstalled: "rtk \u672C\u4F53\u5DF2\u5B89\u88C5\uFF1BPATH \u9700\u6CE8\u9500\u91CD\u767B\u540E\u5BF9\u4F1A\u8BDD\u751F\u6548\uFF0C\u63D2\u4EF6\u94A9\u5B50\u5373\u65F6\u751F\u6548",
|
|
209
250
|
rtkWhitelistTitle: "\u767D\u540D\u5355\uFF08\u4E0D\u538B\u7F29\u76F4\u63A5\u653E\u884C\uFF09",
|
|
210
251
|
rtkBuiltinLabel: "\u5185\u7F6E\u653E\u884C\uFF08\u53EA\u8BFB\uFF0C\u968F\u63D2\u4EF6\u66F4\u65B0\uFF09\uFF1A",
|
|
211
252
|
rtkWhitelistDesc: "\u6BCF\u6761 name\uFF08\u5982 docker\uFF09\u6216 git:name\uFF08\u5982 git:clone\uFF09\u3002\u8F93\u51FA\u6781\u5C0F\u6216\u7EAF\u526F\u4F5C\u7528\u7684\u547D\u4EE4\u65E0\u9700\u538B\u7F29\uFF0C\u52A0\u5165\u540E\u4E0D\u518D\u538B\u7F29\uFF1B\u5185\u7F6E\u7684 git add/commit/push\u3001mkdir/cp \u7B49\u4E0D\u53EF\u79FB\u9664\u3002\u5220\u9664\u672C\u6587\u4EF6\u5373\u6062\u590D\u9ED8\u8BA4\u3002",
|
|
@@ -218,12 +259,25 @@
|
|
|
218
259
|
tabHeadroom: "Headroom",
|
|
219
260
|
headroomDesc: "Headroom \u63D2\u4EF6\uFF1A\u672C\u5730\u538B\u7F29\u4EE3\u7406\u9A7B\u7559 127.0.0.1\uFF08\u9ED8\u8BA4 8787 \u7AEF\u53E3\uFF09\uFF0C\u538B\u7F29\u53D1\u5F80\u6A21\u578B\u7684\u4E0A\u4E0B\u6587\u4EE5\u7701 token\uFF08/hr-* \u547D\u4EE4\u7F16\u8F91\u540C\u4E00\u914D\u7F6E\uFF09\u3002\u538B\u7F29\u8BBE\u5907\u4E0E\u7701\u7535\u5207\u6362\u4FDD\u5B58\u540E\u7ACB\u5373\u751F\u6548\uFF1B\u5207\u6362\u8BBE\u5907\u4F1A\u91CD\u542F\u4EE3\u7406\uFF0C\u6B63\u5728\u5904\u7406\u7684\u8BF7\u6C42\u53EF\u80FD\u4E2D\u65AD\u4E00\u6B21\u3002",
|
|
220
261
|
headroomBinMissing: "\u672A\u627E\u5230 headroom \u7A0B\u5E8F\uFF0C\u4EE3\u7406\u65E0\u6CD5\u542F\u52A8\uFF1B\u5B89\u88C5 headroom \u540E\u4EE5\u4E0B\u8BBE\u7F6E\u81EA\u52A8\u751F\u6548",
|
|
262
|
+
hrInstallBin: "\u5B89\u88C5 headroom \u672C\u4F53",
|
|
263
|
+
hrBinInstalled: "headroom \u672C\u4F53\u5DF2\u5B89\u88C5\uFF1B\u91CD\u65B0\u6253\u5F00\u4F1A\u8BDD\u540E\u4EE3\u7406\u53EF\u7528\uFF08SessionStart \u94A9\u5B50\u81EA\u52A8\u62C9\u8D77\uFF09",
|
|
221
264
|
headroomInstallTitle: "\u672A\u5B89\u88C5 headroom \u63D2\u4EF6",
|
|
222
265
|
headroomInstallDesc: "\u4ECE zcode-plugins \u5E02\u573A\u5B89\u88C5\u540E\u5373\u53EF\u5728\u6B64\u7BA1\u7406\u538B\u7F29\u4EE3\u7406\uFF1B\u5EFA\u8BAE\u5B89\u88C5\u540E\u91CD\u542F\u4F1A\u8BDD\u751F\u6548\u3002",
|
|
223
266
|
headroomInstall: "\u5B89\u88C5",
|
|
224
267
|
headroomInstalling: "\u5B89\u88C5\u4E2D\u2026",
|
|
225
268
|
headroomInstalled: "\u5DF2\u5B89\u88C5 headroom \u63D2\u4EF6",
|
|
226
269
|
headroomInstallRetry: "\u5B89\u88C5\u672A\u751F\u6548\uFF0C\u8BF7\u91CD\u8BD5\u6216\u624B\u52A8\u5728\u63D2\u4EF6\u5E02\u573A\u5B89\u88C5",
|
|
270
|
+
pluginInstallCardTitle: "\u672A\u5B89\u88C5 {name} \u63D2\u4EF6",
|
|
271
|
+
pluginInstallCardDesc: "\u4ECE zcode-plugins \u5E02\u573A\u5B89\u88C5\u540E\u5373\u53EF\u5728\u6B64\u7BA1\u7406\uFF1B\u5EFA\u8BAE\u5B89\u88C5\u540E\u91CD\u542F\u4F1A\u8BDD\u751F\u6548\u3002",
|
|
272
|
+
pluginInstallDone: "\u5DF2\u5B89\u88C5 {name} \u63D2\u4EF6",
|
|
273
|
+
pluginEnable: "\u542F\u7528",
|
|
274
|
+
hrStarting: "\u6B63\u5728\u542F\u52A8\u538B\u7F29\u4EE3\u7406\u2026",
|
|
275
|
+
hrStarted: "\u538B\u7F29\u4EE3\u7406\u5DF2\u542F\u52A8",
|
|
276
|
+
hrStartTimeout: "\u4EE3\u7406\u542F\u52A8\u8D85\u65F6\uFF0890 \u79D2\uFF09\uFF0C\u8BF7\u68C0\u67E5 ~/.zcode-headroom-proxy.log",
|
|
277
|
+
hrStopping: "\u6B63\u5728\u505C\u6B62\u538B\u7F29\u4EE3\u7406\u2026",
|
|
278
|
+
hrRestarting: "\u6B63\u5728\u91CD\u542F\u538B\u7F29\u4EE3\u7406\u2026",
|
|
279
|
+
hrStopped: "\u538B\u7F29\u4EE3\u7406\u5DF2\u505C\u6B62",
|
|
280
|
+
hrUsageNone: "\u5F53\u524D\u6CA1\u6709\u8D70 headroom \u7684\u4F9B\u5E94\u5546\uFF0C\u672A\u5207\u6362",
|
|
227
281
|
headroomLoadFailed: "\u8BFB\u53D6 Headroom \u914D\u7F6E\u5931\u8D25",
|
|
228
282
|
headroomStatusTitle: "\u8FD0\u884C\u72B6\u6001",
|
|
229
283
|
headroomStatusLoadFailed: "\u8BFB\u53D6\u8FD0\u884C\u72B6\u6001\u5931\u8D25",
|
|
@@ -249,7 +303,7 @@
|
|
|
249
303
|
headroomRestart: "\u91CD\u542F",
|
|
250
304
|
headroomStopAction: "\u505C\u6B62",
|
|
251
305
|
headroomStopTitle: "\u505C\u6B62 Headroom \u4EE3\u7406",
|
|
252
|
-
headroomStopDesc: "\u505C\u6B62\u540E\uFF0CZCode \u4E2D\u6307\u5411\u8BE5\u4EE3\u7406\uFF08127.0.0.1\uFF09\u7684\
|
|
306
|
+
headroomStopDesc: "\u505C\u6B62\u540E\uFF0CZCode \u53CA\u5176\u4ED6\u7A0B\u5E8F\u4E2D\u6307\u5411\u8BE5\u4EE3\u7406\uFF08127.0.0.1\uFF09\u7684\u8BF7\u6C42\u90FD\u4F1A\u5931\u8D25\uFF0C\u76F4\u81F3\u91CD\u65B0\u542F\u52A8\u4EE3\u7406\u3002headroom \u662F\u5171\u4EAB\u7684\uFF0C\u5176\u4ED6\u5DE5\u5177\u53EF\u80FD\u6B63\u5728\u4F7F\u7528\u3002\u786E\u8BA4\u505C\u6B62\uFF1F",
|
|
253
307
|
headroomStoppedWarn: "\u4EE3\u7406\u5DF2\u505C\u6B62\uFF1B\u6307\u5411 127.0.0.1 \u7684\u4F9B\u5E94\u5546\u5C06\u65E0\u6CD5\u8FDE\u63A5",
|
|
254
308
|
headroomBackend: "\u538B\u7F29\u8BBE\u5907",
|
|
255
309
|
headroomBackendAuto: "\u81EA\u52A8 \xB7 \u663E\u5361\u4F18\u5148",
|
|
@@ -267,8 +321,6 @@
|
|
|
267
321
|
headroomInterval: "\u76D1\u89C6\u95F4\u9694",
|
|
268
322
|
headroomIntervalDesc: "\u7701\u7535\u76D1\u89C6\u5668\u8F6E\u8BE2\u7535\u6E90\u72B6\u6001\u7684\u95F4\u9694\uFF0810\u20133600 \u79D2\uFF0C\u9ED8\u8BA4 60\uFF09\uFF1B\u4FDD\u5B58\u540E\u4ECE\u4E0B\u4E00\u8F6E\u5DE1\u68C0\u8D77\u751F\u6548\uFF0C\u65E0\u9700\u91CD\u542F\u3002",
|
|
269
323
|
headroomSecUnit: "\u79D2",
|
|
270
|
-
headroomVersionPlugin: "\u63D2\u4EF6",
|
|
271
|
-
headroomVersionBin: "\u7A0B\u5E8F",
|
|
272
324
|
upgradeCheck: "\u68C0\u67E5\u66F4\u65B0",
|
|
273
325
|
upgradeChecking: "\u68C0\u67E5\u4E2D\u2026",
|
|
274
326
|
upgradeUpToDate: "\u5DF2\u662F\u6700\u65B0\uFF08{v}\uFF09",
|
|
@@ -330,16 +382,24 @@
|
|
|
330
382
|
agentsSave: "Save",
|
|
331
383
|
agentsSaved: "Global prompt saved.",
|
|
332
384
|
agentsLoadFailed: "Failed to load the global prompt",
|
|
333
|
-
proxyDesc: "Set an HTTP proxy for network access made by the local helper: plugin marketplace updates and installs,
|
|
385
|
+
proxyDesc: "Set an HTTP proxy for network access made by the local helper: plugin marketplace updates and installs, plugin dependency installs and upgrades, and WebDAV sync can all use it \u2014 pick the scopes with the toggles below. Does not affect the ZCode app itself or model requests. Applies immediately.",
|
|
334
386
|
proxyPlaceholder: "http://127.0.0.1:7890",
|
|
335
387
|
proxySave: "Save",
|
|
336
388
|
proxySaved: "Proxy settings saved.",
|
|
337
389
|
proxyHint: "Save empty to clear the proxy.",
|
|
338
390
|
proxyTest: "Test",
|
|
339
391
|
proxyTesting: "Testing\u2026",
|
|
392
|
+
proxyTestEmpty: "Enter a proxy address first",
|
|
340
393
|
proxyTestFailed: "Test failed",
|
|
394
|
+
proxyScopePlugins: "Plugin marketplace",
|
|
395
|
+
proxyScopePluginsDesc: "Marketplace checks, installs and uninstalls (zcode CLI git operations) go through the proxy.",
|
|
396
|
+
proxyScopeDeps: "Plugin dependencies",
|
|
397
|
+
proxyScopeDepsDesc: "headroom and rtk installs, update checks and upgrades (pip and GitHub downloads) go through the proxy.",
|
|
398
|
+
proxyScopeSync: "Sync",
|
|
399
|
+
proxyScopeSyncDesc: "WebDAV upload and download go through the proxy. Off by default: domestic WebDAV providers work fine direct, and a stopped proxy breaks sync.",
|
|
341
400
|
tabSync: "Sync",
|
|
342
|
-
|
|
401
|
+
tabDebug: "Debug",
|
|
402
|
+
syncDesc: "Manually back up ZCode Pro settings and model settings to WebDAV, or restore them on a new computer. The two items are stored as separate files, so you can upload or overwrite either one alone; every upload also keeps a timestamped history version and download lets you pick any of them. Data moves only when you click, never automatically.",
|
|
343
403
|
syncUrlPlaceholder: "https://dav.example.com/dav/",
|
|
344
404
|
syncDir: "\u4E0A\u4F20\u76EE\u5F55",
|
|
345
405
|
syncDirPlaceholder: "zcode-pro",
|
|
@@ -347,7 +407,7 @@
|
|
|
347
407
|
syncPassword: "Password",
|
|
348
408
|
syncSave: "Save",
|
|
349
409
|
syncSaved: "Sync settings saved.",
|
|
350
|
-
syncFormHint: "Sync files go
|
|
410
|
+
syncFormHint: "Sync files go inside the folder (default zcode-pro, multi-level allowed, created automatically): zcodepro.json and model.json are always the latest version; timestamped history versions are kept alongside.",
|
|
351
411
|
syncRecLink: "Jianguoyun WebDAV",
|
|
352
412
|
syncRecSuffix: " \u2014 use the app password, not your account password.",
|
|
353
413
|
syncIncludeZcp: "ZCode Pro settings",
|
|
@@ -357,16 +417,44 @@
|
|
|
357
417
|
syncUpload: "Upload",
|
|
358
418
|
syncDownload: "Download",
|
|
359
419
|
syncUploading: "Uploading\u2026",
|
|
360
|
-
syncDownloading: "Downloading\u2026",
|
|
361
420
|
syncUploaded: "Uploaded to the server.",
|
|
362
421
|
syncDownloaded: "Restored from the server.",
|
|
363
422
|
syncLastPush: "Last upload",
|
|
364
423
|
syncLastPull: "Last download",
|
|
365
424
|
syncNever: "never",
|
|
366
425
|
syncConfirmTitle: "Download from the server",
|
|
367
|
-
syncConfirmDesc: "
|
|
368
|
-
syncConfirmGo: "
|
|
426
|
+
syncConfirmDesc: "The selected file will overwrite the matching local section (a .zcodepro-backup copy is kept next to each file); your local sync config and credentials stay untouched. Restarting ZCode is recommended after restoring model settings. Import now?",
|
|
427
|
+
syncConfirmGo: "Import",
|
|
428
|
+
syncPickDesc: "Fixed names are always the latest version; timestamped files are the history each upload leaves behind. Import overwrites the matching local section.",
|
|
429
|
+
syncVerDeleteLatestNote: 'Note: this is the "latest" file that older zcode-pro installs download from; deleting it breaks their download. Timestamped history versions are not affected.',
|
|
369
430
|
syncHint: "Sync credentials are stored locally in zcodepro.json only; model settings contain the API keys of custom providers and go to your own WebDAV only.",
|
|
431
|
+
syncTest: "Test",
|
|
432
|
+
syncTesting: "Testing\u2026",
|
|
433
|
+
syncTestEmpty: "Enter the WebDAV URL first",
|
|
434
|
+
syncTestFailed: "Test failed",
|
|
435
|
+
syncTestStepConnect: "Connect",
|
|
436
|
+
syncTestStepDir: "Folder",
|
|
437
|
+
syncTestStepList: "Files",
|
|
438
|
+
syncTestFilesFound: "{n} backup file(s) on the server",
|
|
439
|
+
syncPickTitle: "Select a file",
|
|
440
|
+
syncPickLoading: "Loading files from the server\u2026",
|
|
441
|
+
syncPickEmpty: "No backups on the server yet. Upload from a computer first.",
|
|
442
|
+
syncVerImport: "Import",
|
|
443
|
+
syncVerImporting: "Importing\u2026",
|
|
444
|
+
syncVerDelete: "Delete",
|
|
445
|
+
syncVerSave: "Save to disk",
|
|
446
|
+
syncVerSaving: "Saving\u2026",
|
|
447
|
+
syncVerLatest: "Latest",
|
|
448
|
+
syncVerDeleteTitle: "Delete server file",
|
|
449
|
+
syncVerDeleteDesc: "This backup will be deleted from the server and cannot be recovered: ",
|
|
450
|
+
syncVerDeleted: "Backup deleted from the server.",
|
|
451
|
+
syncVerSaved: "Saved to",
|
|
452
|
+
devMode: "Developer mode",
|
|
453
|
+
devModeRowDesc: 'Shows the "Reload ZCode Pro" button; can also be enabled with the ZCODEPRO_DEV=1 environment variable. This tab is visible only while developer mode is active.',
|
|
454
|
+
devModeDesc: 'For development: after changing zcode-pro code, click "Reload ZCode Pro" instead of restarting ZCode. It builds automatically (when running from the source repo), restarts the ZCode Pro launcher process (fresh helper and injected script), and every ZCode window refreshes and re-injects. The ZCode app itself and all sessions stay untouched.',
|
|
455
|
+
devReload: "Reload ZCode Pro",
|
|
456
|
+
devReloading: "Reloading\u2026",
|
|
457
|
+
devReloadDesc: "Every ZCode window refreshes automatically within 2-3 seconds to load the new script.",
|
|
370
458
|
rowGapName: "Paragraph spacing",
|
|
371
459
|
rowGapDesc: "Vertical spacing between text blocks (turns, paragraphs inside answers).",
|
|
372
460
|
listSpacingName: "List spacing",
|
|
@@ -383,6 +471,8 @@
|
|
|
383
471
|
tableCellPaddingDesc: "Padding inside table cells; left input is vertical, right is horizontal.",
|
|
384
472
|
lineHeightName: "Answer line height",
|
|
385
473
|
lineHeightDesc: "Line height of answer text (multiplier).",
|
|
474
|
+
thinkingLineHeightName: "Work-log line height",
|
|
475
|
+
thinkingLineHeightDesc: "Line height of the \u201Cworked for\u2026\u201D history panel (tool entries and reasoning, multiplier).",
|
|
386
476
|
userLineHeightName: "Question line height",
|
|
387
477
|
userLineHeightDesc: "Line height of question text (multiplier).",
|
|
388
478
|
contentWidthName: "Content width",
|
|
@@ -446,7 +536,7 @@
|
|
|
446
536
|
featurePinnedExpand: "Keep projects collapsed for pinned sessions (experimental)",
|
|
447
537
|
featurePinnedExpandDesc: "Keeps the project collapsed after clicking a pinned session. Note: it briefly expands first, then collapses.",
|
|
448
538
|
featureAutoUpdatePlugins: "Auto-update zcode-plugins plugins",
|
|
449
|
-
featureAutoUpdatePluginsDesc: "Checks and updates installed zcode-plugins plugins on startup (
|
|
539
|
+
featureAutoUpdatePluginsDesc: "Checks and updates installed zcode-plugins plugins on startup (updates only \u2014 never installs; uninstalled plugins stay uninstalled). Updates apply to new sessions.",
|
|
450
540
|
pluginsUpdateTitle: "Plugin updates \xB7 zcode-plugins",
|
|
451
541
|
pluginsCheckNow: "Check & update",
|
|
452
542
|
pluginsUpdating: "Updating plugins\u2026",
|
|
@@ -458,7 +548,7 @@
|
|
|
458
548
|
pluginsAutoUpdated: "zcode-plugins updated",
|
|
459
549
|
tabVision: "Vision",
|
|
460
550
|
visionDesc: "When the main model cannot see images (e.g. glm-5.3), images in messages are recognized by the vision models below and passed to the main model as text (zcode-vision plugin; /vision-* commands edit the same file). Changes save automatically.",
|
|
461
|
-
visionEnabled: "Enable
|
|
551
|
+
visionEnabled: "Enable",
|
|
462
552
|
visionForceIntercept: "Intercept even if the main model sees images",
|
|
463
553
|
visionMode: "Chain mode",
|
|
464
554
|
visionModeFallback: "Fallback",
|
|
@@ -483,21 +573,21 @@
|
|
|
483
573
|
visionResetChainConfirm: "Reset chain mode and the proxy list to the default 2-level chain (glm-session \u2192 glm-flash)? Current proxy edits will be lost. Continue?",
|
|
484
574
|
visionBaseUrl: "Base URL",
|
|
485
575
|
visionModel: "Model",
|
|
486
|
-
visionFormat: "Format",
|
|
487
576
|
visionApiKey: "API Key",
|
|
488
577
|
visionApiKeyHint: "Leave empty to reuse the GLM subscription key",
|
|
489
578
|
visionPrompt: "Recognition prompt ({prev} = previous step in pipeline)",
|
|
490
579
|
visionTest: "Test",
|
|
491
580
|
visionTesting: "Testing\u2026",
|
|
492
581
|
visionTestFailed: "Vision proxy test failed",
|
|
493
|
-
visionTestOutput: "Test output",
|
|
494
582
|
visionCompressKB: "Compress threshold KB",
|
|
495
583
|
visionCompressKBHint: "Images above this size are compressed first (max edge 2000, JPEG); 0 = never",
|
|
496
584
|
visionLoadFailed: "Failed to load the vision config",
|
|
497
585
|
tabRtk: "rtk",
|
|
498
586
|
rtkDesc: "rtk plugin: compresses common dev command output by 60-90% before it reaches the context (/rtk-* commands edit the same files). Changes save automatically and apply immediately.",
|
|
499
|
-
rtkEnabled: "Enable
|
|
587
|
+
rtkEnabled: "Enable",
|
|
500
588
|
rtkNotInstalled: "rtk is not installed. The settings below take effect after installation (/rtk-setup in a session).",
|
|
589
|
+
rtkInstallBin: "Install rtk binary",
|
|
590
|
+
rtkBinInstalled: "rtk installed; PATH takes effect for sessions after signing out and back in \u2014 the plugin hook works immediately",
|
|
501
591
|
rtkWhitelistTitle: "Whitelist (pass through without compression)",
|
|
502
592
|
rtkBuiltinLabel: "Built-in exemptions (read-only, follow plugin updates):",
|
|
503
593
|
rtkWhitelistDesc: "Each entry is name (e.g. docker) or git:name (e.g. git:clone). Commands with tiny or no output need no compression; adding them skips compression. Built-ins (git add/commit/push, mkdir/cp, \u2026) cannot be removed. Delete the file to reset.",
|
|
@@ -510,12 +600,25 @@
|
|
|
510
600
|
tabHeadroom: "Headroom",
|
|
511
601
|
headroomDesc: "Headroom plugin: a local compression proxy on 127.0.0.1 (port 8787 by default) that compresses context sent to the model to save tokens (/hr-* commands edit the same file). Device and power-save changes apply immediately; switching the device restarts the proxy, so requests in progress may be interrupted once.",
|
|
512
602
|
headroomBinMissing: "The headroom program was not found, so the proxy cannot start. The settings below take effect once it is installed.",
|
|
603
|
+
hrInstallBin: "Install headroom binary",
|
|
604
|
+
hrBinInstalled: "headroom installed; reopen a session and the hook will start the proxy automatically",
|
|
513
605
|
headroomInstallTitle: "headroom plugin not installed",
|
|
514
606
|
headroomInstallDesc: "Install it from the zcode-plugins marketplace to manage the compression proxy here; restarting the session afterwards is recommended.",
|
|
515
607
|
headroomInstall: "Install",
|
|
516
608
|
headroomInstalling: "Installing\u2026",
|
|
517
609
|
headroomInstalled: "headroom plugin installed",
|
|
518
610
|
headroomInstallRetry: "Installation did not take effect; retry or install it from the marketplace manually",
|
|
611
|
+
pluginInstallCardTitle: "{name} plugin not installed",
|
|
612
|
+
pluginInstallCardDesc: "Install it from the zcode-plugins marketplace to manage it here; restarting the session afterwards is recommended.",
|
|
613
|
+
pluginInstallDone: "{name} plugin installed",
|
|
614
|
+
pluginEnable: "Enable",
|
|
615
|
+
hrStarting: "Starting compression proxy\u2026",
|
|
616
|
+
hrStarted: "Compression proxy started",
|
|
617
|
+
hrStartTimeout: "Proxy start timed out (90s); check ~/.zcode-headroom-proxy.log",
|
|
618
|
+
hrStopping: "Stopping compression proxy\u2026",
|
|
619
|
+
hrRestarting: "Restarting compression proxy\u2026",
|
|
620
|
+
hrStopped: "Compression proxy stopped",
|
|
621
|
+
hrUsageNone: "No providers route through headroom; nothing changed",
|
|
519
622
|
headroomLoadFailed: "Failed to load the Headroom config",
|
|
520
623
|
headroomStatusTitle: "Status",
|
|
521
624
|
headroomStatusLoadFailed: "Failed to load the status",
|
|
@@ -541,7 +644,7 @@
|
|
|
541
644
|
headroomRestart: "Restart",
|
|
542
645
|
headroomStopAction: "Stop",
|
|
543
646
|
headroomStopTitle: "Stop the Headroom proxy",
|
|
544
|
-
headroomStopDesc: "
|
|
647
|
+
headroomStopDesc: "Requests from ZCode and other apps pointing at this proxy (127.0.0.1) will fail until it is started again. headroom is shared \u2014 other tools may be using it. Stop it?",
|
|
545
648
|
headroomStoppedWarn: "Proxy stopped; providers pointing at 127.0.0.1 cannot connect.",
|
|
546
649
|
headroomBackend: "Compression device",
|
|
547
650
|
headroomBackendAuto: "Auto \xB7 GPU first",
|
|
@@ -559,8 +662,6 @@
|
|
|
559
662
|
headroomInterval: "Watch interval",
|
|
560
663
|
headroomIntervalDesc: "Seconds between power checks (10\u20133600, default 60); applies from the next round, no restart needed.",
|
|
561
664
|
headroomSecUnit: "s",
|
|
562
|
-
headroomVersionPlugin: "plugin",
|
|
563
|
-
headroomVersionBin: "program",
|
|
564
665
|
upgradeCheck: "Check update",
|
|
565
666
|
upgradeChecking: "Checking\u2026",
|
|
566
667
|
upgradeUpToDate: "Up to date ({v})",
|
|
@@ -678,7 +779,9 @@
|
|
|
678
779
|
"sync-remote-missing": "No synced data on the server yet; upload from another computer first",
|
|
679
780
|
"sync-remote-invalid": "The URL already holds a different file; use another file path",
|
|
680
781
|
"sync-request": "The WebDAV request failed",
|
|
681
|
-
"sync-run": "Sync failed"
|
|
782
|
+
"sync-run": "Sync failed",
|
|
783
|
+
"sync-file-invalid": "Invalid backup file name",
|
|
784
|
+
"sync-export": "Failed to save the backup to disk"
|
|
682
785
|
};
|
|
683
786
|
function errText(res) {
|
|
684
787
|
if (!res) return "";
|
|
@@ -753,8 +856,9 @@
|
|
|
753
856
|
"div",
|
|
754
857
|
{
|
|
755
858
|
id: "__zcodepro_toast__",
|
|
756
|
-
class: "fixed bottom-6
|
|
757
|
-
|
|
859
|
+
class: "fixed bottom-6 z-[100] flex max-w-md items-center gap-2 rounded-lg border px-4 py-3 text-ui-sm shadow-lg " + (kind === "error" ? "border-destructive/40 bg-menu text-foreground" : "border-border bg-menu text-foreground"),
|
|
860
|
+
// left 用内联样式:ZCode 的 Tailwind 未编译 left-6/right-6 工具类(bottom-6 有)
|
|
861
|
+
style: "animation:zcodepro-fade-in .18s ease; left: 1.5rem;"
|
|
758
862
|
},
|
|
759
863
|
h("span", { class: "truncate" }, text)
|
|
760
864
|
);
|
|
@@ -2361,6 +2465,8 @@
|
|
|
2361
2465
|
// 单元格左右边距(应用默认 3px)
|
|
2362
2466
|
lineHeight: 1.75,
|
|
2363
2467
|
// 回答行高(leading-[1.75],挂在答案内容容器上)
|
|
2468
|
+
thinkingLineHeight: 1.5,
|
|
2469
|
+
// 思考行高:“已工作/工作中”过程视图的行距(实测应用默认 1.5;范围见 buildCss 注释)
|
|
2364
2470
|
userLineHeight: 1.5,
|
|
2365
2471
|
// 提问行高(用户消息文本容器,默认 normal=1.5)
|
|
2366
2472
|
contentWidth: null,
|
|
@@ -2457,6 +2563,12 @@
|
|
|
2457
2563
|
if (typeof lh === "number" && Number.isFinite(lh) && lh >= 0.8) {
|
|
2458
2564
|
parts.push(`${CONV} .space-y-4{line-height:${lh} !important;}`);
|
|
2459
2565
|
}
|
|
2566
|
+
const tlh = styles.thinkingLineHeight;
|
|
2567
|
+
if (typeof tlh === "number" && Number.isFinite(tlh) && tlh >= 0.8) {
|
|
2568
|
+
parts.push(
|
|
2569
|
+
`[data-testid^="chat-assistant-history-content"]{line-height:${tlh} !important;}`
|
|
2570
|
+
);
|
|
2571
|
+
}
|
|
2460
2572
|
const ulh = styles.userLineHeight;
|
|
2461
2573
|
if (typeof ulh === "number" && Number.isFinite(ulh) && ulh >= 0.8) {
|
|
2462
2574
|
parts.push(`${CONV} [class*="user-row"] .whitespace-pre-wrap{line-height:${ulh} !important;}`);
|
|
@@ -2553,7 +2665,10 @@
|
|
|
2553
2665
|
tableCellPaddingV: `${CONV} td, ${CONV} th`,
|
|
2554
2666
|
tableCellPaddingH: `${CONV} td, ${CONV} th`,
|
|
2555
2667
|
codeLineHeight: `${CONV} diffs-container, ${CONV} pre`,
|
|
2556
|
-
lineHeight: `${CONV} .space-y-4`,
|
|
2668
|
+
lineHeight: `${CONV} .space-y-4:not([data-reasoning-content] *)`,
|
|
2669
|
+
// 思考行高作用在“已工作/工作中”过程视图容器上;视图折叠未挂载时不标
|
|
2670
|
+
// (触发行不属此设置范围,不额外描边)
|
|
2671
|
+
thinkingLineHeight: `[data-testid^="chat-assistant-history-content"]`,
|
|
2557
2672
|
userLineHeight: `${CONV} [class*="user-row"] .whitespace-pre-wrap`,
|
|
2558
2673
|
contentWidth: "[data-v4-timeline-content-column]",
|
|
2559
2674
|
sidebarProjectSpacing: '[data-testid^="workspace-item-"]',
|
|
@@ -2600,11 +2715,13 @@
|
|
|
2600
2715
|
} catch {
|
|
2601
2716
|
}
|
|
2602
2717
|
}
|
|
2603
|
-
function makeUpgradeControls({ endpoint, metaRefresh }) {
|
|
2718
|
+
function makeUpgradeControls({ endpoint, metaRefresh, idleText }) {
|
|
2604
2719
|
const L = t();
|
|
2605
2720
|
const state = h("span", { class: "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed text-foreground-subtle" });
|
|
2721
|
+
const hasIdle = () => typeof idleText === "function";
|
|
2606
2722
|
const setState = (text, kind = "") => {
|
|
2607
|
-
|
|
2723
|
+
const shown = text || (hasIdle() ? idleText() || "" : "");
|
|
2724
|
+
state.textContent = shown ? kind === "error" ? shown : ` \xB7 ${shown}` : "";
|
|
2608
2725
|
state.className = "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed " + (kind === "error" ? "text-destructive" : "text-foreground-subtle");
|
|
2609
2726
|
};
|
|
2610
2727
|
let latest = null;
|
|
@@ -2722,6 +2839,7 @@
|
|
|
2722
2839
|
const res = await rpc(endpoint + "/upgrade");
|
|
2723
2840
|
if (res.ok && res.upgrade && res.upgrade.running) pollStart();
|
|
2724
2841
|
})();
|
|
2842
|
+
setState("");
|
|
2725
2843
|
return { btn, state, stop: stopPoll };
|
|
2726
2844
|
}
|
|
2727
2845
|
function openSettingsDialog() {
|
|
@@ -2930,7 +3048,7 @@
|
|
|
2930
3048
|
const runPluginsUpdate = async () => {
|
|
2931
3049
|
pluginsBtn.disabled = true;
|
|
2932
3050
|
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
2933
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {
|
|
3051
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
2934
3052
|
pluginsBtn.disabled = false;
|
|
2935
3053
|
if (!res.ok) {
|
|
2936
3054
|
pluginsStatusLine.textContent = "";
|
|
@@ -2991,7 +3109,8 @@
|
|
|
2991
3109
|
const paneVision = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2992
3110
|
const paneRtk = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2993
3111
|
const paneHeadroom = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2994
|
-
const
|
|
3112
|
+
const paneDebug = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
3113
|
+
const panes = { features: paneFeatures, styles: paneStyles, perf: panePerf, agents: paneAgents, proxy: paneProxy, sync: paneSync, vision: paneVision, headroom: paneHeadroom, rtk: paneRtk, debug: paneDebug };
|
|
2995
3114
|
const tabDefs = [
|
|
2996
3115
|
["features", L.tabFeatures],
|
|
2997
3116
|
["styles", L.tabStyles],
|
|
@@ -3001,7 +3120,10 @@
|
|
|
3001
3120
|
["sync", L.tabSync],
|
|
3002
3121
|
["vision", L.tabVision],
|
|
3003
3122
|
["headroom", L.tabHeadroom],
|
|
3004
|
-
["rtk", L.tabRtk]
|
|
3123
|
+
["rtk", L.tabRtk],
|
|
3124
|
+
// “调试”标签页只对开发模式生效的用户显示(配置开关或 ZCODEPRO_DEV=1),
|
|
3125
|
+
// 普通用户不可见
|
|
3126
|
+
...config.devMode === true || config.devActive === true ? [["debug", L.tabDebug]] : []
|
|
3005
3127
|
];
|
|
3006
3128
|
const tablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist mt-4" });
|
|
3007
3129
|
const renderTabs = () => tablist.replaceChildren(...tabDefs.map(([id, label]) => h("button", {
|
|
@@ -3119,6 +3241,7 @@
|
|
|
3119
3241
|
styleCell(L.rowGapName, L.rowGapDesc, "rowGap"),
|
|
3120
3242
|
styleCell(L.userLineHeightName, L.userLineHeightDesc, "userLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3121
3243
|
styleCell(L.lineHeightName, L.lineHeightDesc, "lineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3244
|
+
styleCell(L.thinkingLineHeightName, L.thinkingLineHeightDesc, "thinkingLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3122
3245
|
styleCell(L.codeLineHeightName, L.codeLineHeightDesc, "codeLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3123
3246
|
styleCell(L.listSpacingName, L.listSpacingDesc, "listSpacing"),
|
|
3124
3247
|
styleCell(L.listItemSpacingName, L.listItemSpacingDesc, "listItemSpacing"),
|
|
@@ -3278,6 +3401,11 @@
|
|
|
3278
3401
|
}, "shrink-0");
|
|
3279
3402
|
const runProxyTest = async () => {
|
|
3280
3403
|
if (proxyTesting) return;
|
|
3404
|
+
if (!proxyInput.value.trim()) {
|
|
3405
|
+
proxyTestState.className = "mt-2 text-ui-xs/relaxed text-amber-500";
|
|
3406
|
+
proxyTestState.textContent = L.proxyTestEmpty;
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3281
3409
|
proxyTesting = true;
|
|
3282
3410
|
proxyTestBtn.disabled = true;
|
|
3283
3411
|
proxyTestBtn.textContent = L.proxyTesting;
|
|
@@ -3297,6 +3425,37 @@
|
|
|
3297
3425
|
proxyTestState.className = "mt-2 text-ui-xs/relaxed " + (allOk ? "text-foreground-subtle" : "text-amber-500");
|
|
3298
3426
|
proxyTestState.textContent = `${res.proxy}\uFF1A${parts.join(" \xB7 ")}`;
|
|
3299
3427
|
};
|
|
3428
|
+
const persistProxyScope = async (partial) => {
|
|
3429
|
+
const res = await rpc("/config", { method: "POST", body: { proxyScopes: partial } });
|
|
3430
|
+
if (!res.ok) {
|
|
3431
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3432
|
+
return false;
|
|
3433
|
+
}
|
|
3434
|
+
if (res.config && res.config.proxyScopes) config.proxyScopes = res.config.proxyScopes;
|
|
3435
|
+
return true;
|
|
3436
|
+
};
|
|
3437
|
+
const proxyScopeWrap = h("div");
|
|
3438
|
+
const renderProxyScopes = () => {
|
|
3439
|
+
const sc = config.proxyScopes || {};
|
|
3440
|
+
proxyScopeWrap.replaceChildren(
|
|
3441
|
+
settingRow(L.proxyScopePlugins, L.proxyScopePluginsDesc, sc.plugins !== false, async () => {
|
|
3442
|
+
const next = !(sc.plugins !== false);
|
|
3443
|
+
if (await persistProxyScope({ plugins: next })) sc.plugins = next;
|
|
3444
|
+
renderProxyScopes();
|
|
3445
|
+
}),
|
|
3446
|
+
settingRow(L.proxyScopeDeps, L.proxyScopeDepsDesc, sc.deps !== false, async () => {
|
|
3447
|
+
const next = !(sc.deps !== false);
|
|
3448
|
+
if (await persistProxyScope({ deps: next })) sc.deps = next;
|
|
3449
|
+
renderProxyScopes();
|
|
3450
|
+
}),
|
|
3451
|
+
settingRow(L.proxyScopeSync, L.proxyScopeSyncDesc, sc.sync === true, async () => {
|
|
3452
|
+
const next = !(sc.sync === true);
|
|
3453
|
+
if (await persistProxyScope({ sync: next })) sc.sync = next;
|
|
3454
|
+
renderProxyScopes();
|
|
3455
|
+
})
|
|
3456
|
+
);
|
|
3457
|
+
};
|
|
3458
|
+
renderProxyScopes();
|
|
3300
3459
|
paneProxy.append(
|
|
3301
3460
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.proxyDesc),
|
|
3302
3461
|
h(
|
|
@@ -3307,7 +3466,8 @@
|
|
|
3307
3466
|
proxyTestBtn
|
|
3308
3467
|
),
|
|
3309
3468
|
h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" }, L.proxyHint),
|
|
3310
|
-
proxyTestState
|
|
3469
|
+
proxyTestState,
|
|
3470
|
+
h("div", { class: "mt-3 divide-y divide-border rounded-xl border border-border" }, proxyScopeWrap)
|
|
3311
3471
|
);
|
|
3312
3472
|
const perfToggleWrap = h("div");
|
|
3313
3473
|
const renderPerfToggle = () => {
|
|
@@ -3414,6 +3574,43 @@
|
|
|
3414
3574
|
syncCheckDirty();
|
|
3415
3575
|
}
|
|
3416
3576
|
};
|
|
3577
|
+
const syncTestState = h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" });
|
|
3578
|
+
let syncTesting = false;
|
|
3579
|
+
const syncTestBtn = btnSmall(L.syncTest, () => {
|
|
3580
|
+
void runSyncTest();
|
|
3581
|
+
}, "shrink-0");
|
|
3582
|
+
const runSyncTest = async () => {
|
|
3583
|
+
if (syncTesting) return;
|
|
3584
|
+
if (!syncUrlInput.value.trim()) {
|
|
3585
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-amber-500";
|
|
3586
|
+
syncTestState.textContent = L.syncTestEmpty;
|
|
3587
|
+
return;
|
|
3588
|
+
}
|
|
3589
|
+
syncTesting = true;
|
|
3590
|
+
syncTestBtn.disabled = true;
|
|
3591
|
+
syncTestBtn.textContent = L.syncTesting;
|
|
3592
|
+
syncTestState.textContent = "";
|
|
3593
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-foreground-subtle";
|
|
3594
|
+
const res = await rpc("/sync/test", { method: "POST", body: { sync: syncFormValues() } });
|
|
3595
|
+
syncTesting = false;
|
|
3596
|
+
syncTestBtn.disabled = false;
|
|
3597
|
+
syncTestBtn.textContent = L.syncTest;
|
|
3598
|
+
if (!res.ok) {
|
|
3599
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-destructive";
|
|
3600
|
+
syncTestState.textContent = L.syncTestFailed + ": " + errText(res);
|
|
3601
|
+
return;
|
|
3602
|
+
}
|
|
3603
|
+
const stepName = { connect: L.syncTestStepConnect, dir: L.syncTestStepDir, list: L.syncTestStepList };
|
|
3604
|
+
const parts = (res.targets || []).map((t2) => `${stepName[t2.step] || t2.step} ${t2.ok ? "\u2713" + (t2.ms != null ? " " + t2.ms + "ms" : "") : "\u2717 " + (t2.error || t2.httpCode || "")}`.trim());
|
|
3605
|
+
const allOk = (res.targets || []).length > 0 && (res.targets || []).every((t2) => t2.ok);
|
|
3606
|
+
let host = syncUrlInput.value.trim();
|
|
3607
|
+
try {
|
|
3608
|
+
host = new URL(host).host;
|
|
3609
|
+
} catch {
|
|
3610
|
+
}
|
|
3611
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed " + (allOk ? "text-foreground-subtle" : "text-amber-500");
|
|
3612
|
+
syncTestState.textContent = `${host}\uFF1A${parts.join(" \xB7 ")}` + (allOk && res.fileCount != null ? `\uFF08${L.syncTestFilesFound.replace("{n}", res.fileCount)}\uFF09` : "");
|
|
3613
|
+
};
|
|
3417
3614
|
const JIANGUO_HELP = "https://help.jianguoyun.com/?p=2064";
|
|
3418
3615
|
const syncRecLine = h("p", { class: "mt-1 text-ui-xs/relaxed text-foreground-subtle" });
|
|
3419
3616
|
if (typeof window.zcode?.openExternal === "function") {
|
|
@@ -3457,56 +3654,216 @@
|
|
|
3457
3654
|
};
|
|
3458
3655
|
renderSyncStatus(savedSync);
|
|
3459
3656
|
const syncUploadBtn = btnSmall(L.syncUpload, () => {
|
|
3460
|
-
void
|
|
3657
|
+
void runSyncPush();
|
|
3461
3658
|
}, "shrink-0", "primary");
|
|
3462
3659
|
const syncDownloadBtn = btnSmall(L.syncDownload, () => {
|
|
3463
|
-
|
|
3660
|
+
openSyncVersionPicker();
|
|
3464
3661
|
}, "shrink-0");
|
|
3465
|
-
const
|
|
3662
|
+
const openSyncVersionPicker = () => {
|
|
3466
3663
|
openDialog({
|
|
3467
|
-
title: L.
|
|
3468
|
-
description: L.
|
|
3469
|
-
width: "
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3664
|
+
title: L.syncPickTitle,
|
|
3665
|
+
description: L.syncPickDesc,
|
|
3666
|
+
width: "max-w-2xl",
|
|
3667
|
+
dismissOnOutside: false,
|
|
3668
|
+
onMount: async ({ body: pickBody, content: content2, close: closePicker }) => {
|
|
3669
|
+
const titleEl2 = content2 && content2.firstElementChild;
|
|
3670
|
+
if (titleEl2 && titleEl2.tagName === "H2") {
|
|
3671
|
+
titleEl2.classList.add("flex", "w-full", "items-center", "justify-between");
|
|
3672
|
+
titleEl2.replaceChildren(
|
|
3673
|
+
h("span", { class: "flex min-w-0 items-center" }, L.syncPickTitle),
|
|
3674
|
+
h("button", {
|
|
3675
|
+
type: "button",
|
|
3676
|
+
class: "zcodepro-close",
|
|
3677
|
+
title: L.close,
|
|
3678
|
+
"aria-label": L.close,
|
|
3679
|
+
onMousedown: (e) => {
|
|
3680
|
+
e.stopPropagation();
|
|
3681
|
+
},
|
|
3682
|
+
onClick: () => {
|
|
3683
|
+
closePicker();
|
|
3684
|
+
}
|
|
3685
|
+
}, "\u2715")
|
|
3686
|
+
);
|
|
3687
|
+
}
|
|
3688
|
+
const listWrap = h("div", { class: "space-y-1" });
|
|
3689
|
+
pickBody.append(listWrap);
|
|
3690
|
+
const fmtSize = (n) => {
|
|
3691
|
+
if (!Number.isFinite(n) || n <= 0) return "";
|
|
3692
|
+
return n >= 1048576 ? (n / 1048576).toFixed(2) + " MB" : Math.max(1, Math.round(n / 1024)) + " KB";
|
|
3693
|
+
};
|
|
3694
|
+
const setStatus = (el) => {
|
|
3695
|
+
listWrap.replaceChildren(el);
|
|
3696
|
+
};
|
|
3697
|
+
const setRowBusy = (btns, busy) => {
|
|
3698
|
+
for (const b of btns) b.disabled = busy;
|
|
3699
|
+
};
|
|
3700
|
+
const versionRow = (f) => {
|
|
3701
|
+
const isLatest = !/-\d{4}-\d{2}-\d{2}T/.test(f.name);
|
|
3702
|
+
const importBtn = btnSmall(L.syncVerImport, () => {
|
|
3703
|
+
confirmImport(f, rowBtns, importBtn);
|
|
3704
|
+
}, "shrink-0");
|
|
3705
|
+
const deleteBtn = btnSmall(L.syncVerDelete, () => {
|
|
3706
|
+
confirmDelete(f, rowBtns, isLatest);
|
|
3707
|
+
}, "shrink-0");
|
|
3708
|
+
const saveBtn = btnSmall(L.syncVerSave, () => {
|
|
3709
|
+
void exportVersion(f, rowBtns, saveBtn);
|
|
3710
|
+
}, "shrink-0");
|
|
3711
|
+
const rowBtns = [importBtn, deleteBtn, saveBtn];
|
|
3712
|
+
return h(
|
|
3713
|
+
"div",
|
|
3714
|
+
{ class: "flex items-center gap-3 rounded-xl border border-border px-3 py-2" },
|
|
3715
|
+
h(
|
|
3716
|
+
"div",
|
|
3717
|
+
{ class: "min-w-0 flex-1" },
|
|
3718
|
+
h(
|
|
3719
|
+
"div",
|
|
3720
|
+
{ class: "flex min-w-0 items-center gap-1.5" },
|
|
3721
|
+
h("span", { class: "truncate font-mono text-ui-xs text-foreground", title: f.name }, f.name),
|
|
3722
|
+
...isLatest ? [h("span", { class: "shrink-0 rounded border border-border px-1.5 text-ui-xs text-foreground-subtle" }, L.syncVerLatest)] : []
|
|
3723
|
+
),
|
|
3724
|
+
h(
|
|
3725
|
+
"div",
|
|
3726
|
+
{ class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" },
|
|
3727
|
+
[fmtSize(f.size), f.lastModified ? new Date(f.lastModified).toLocaleString() : ""].filter(Boolean).join(" \xB7 ")
|
|
3728
|
+
)
|
|
3729
|
+
),
|
|
3730
|
+
h("div", { class: "flex shrink-0 items-center gap-1.5" }, importBtn, deleteBtn, saveBtn)
|
|
3731
|
+
);
|
|
3732
|
+
};
|
|
3733
|
+
const loadList = async () => {
|
|
3734
|
+
setStatus(h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncPickLoading));
|
|
3735
|
+
const res = await rpc("/sync/versions", { method: "POST", body: {} });
|
|
3736
|
+
if (!res.ok) {
|
|
3737
|
+
setStatus(h("p", { class: "text-ui-sm text-destructive" }, L.failed + ": " + errText(res)));
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
const files = res.files || [];
|
|
3741
|
+
if (!files.length) {
|
|
3742
|
+
setStatus(h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncPickEmpty));
|
|
3743
|
+
return;
|
|
3744
|
+
}
|
|
3745
|
+
const parts = [];
|
|
3746
|
+
for (const [prefix, label] of [["zcodepro", L.syncIncludeZcp], ["model", L.syncIncludeModel]]) {
|
|
3747
|
+
const group = files.filter((f) => f.name === `${prefix}.json` || f.name.startsWith(`${prefix}-`));
|
|
3748
|
+
if (!group.length) continue;
|
|
3749
|
+
const latest = group.find((f) => f.name === `${prefix}.json`);
|
|
3750
|
+
const history = group.filter((f) => f !== latest).sort((a, b) => (b.lastModified || 0) - (a.lastModified || 0) || b.name.localeCompare(a.name));
|
|
3751
|
+
parts.push(h(
|
|
3752
|
+
"div",
|
|
3753
|
+
{ class: "px-1 pt-2 text-ui-xs font-medium text-foreground-subtle" },
|
|
3754
|
+
`${label}${isZhLocale() ? "\uFF08" : " ("}${group.length}${isZhLocale() ? "\uFF09" : ")"}`
|
|
3755
|
+
));
|
|
3756
|
+
for (const f of [latest, ...history]) {
|
|
3757
|
+
if (f) parts.push(versionRow(f));
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
listWrap.replaceChildren(...parts);
|
|
3761
|
+
};
|
|
3762
|
+
const confirmImport = (f, rowBtns, importBtn) => {
|
|
3763
|
+
openDialog({
|
|
3764
|
+
title: L.syncConfirmTitle,
|
|
3765
|
+
width: "sm:max-w-md",
|
|
3766
|
+
onMount: ({ body: confirmBody, close: closeConfirm }) => {
|
|
3767
|
+
confirmBody.append(
|
|
3768
|
+
h("p", { class: "mb-2 truncate font-mono text-ui-xs text-foreground-subtle", title: f.name }, f.name),
|
|
3769
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncConfirmDesc),
|
|
3770
|
+
dialogFooter(
|
|
3771
|
+
btnSecondary(L.cancel, () => closeConfirm()),
|
|
3772
|
+
btnPrimary(L.syncConfirmGo, () => {
|
|
3773
|
+
closeConfirm();
|
|
3774
|
+
void importVersion(f, rowBtns, importBtn);
|
|
3775
|
+
}, "min-w-24")
|
|
3776
|
+
)
|
|
3777
|
+
);
|
|
3778
|
+
}
|
|
3779
|
+
});
|
|
3780
|
+
};
|
|
3781
|
+
const importVersion = async (f, rowBtns, importBtn) => {
|
|
3782
|
+
setRowBusy(rowBtns, true);
|
|
3783
|
+
importBtn.textContent = L.syncVerImporting;
|
|
3784
|
+
const res = await rpc("/sync/version/apply", { method: "POST", body: { file: f.name } });
|
|
3785
|
+
setRowBusy(rowBtns, false);
|
|
3786
|
+
importBtn.textContent = L.syncVerImport;
|
|
3787
|
+
if (!res.ok) {
|
|
3788
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3789
|
+
return;
|
|
3790
|
+
}
|
|
3791
|
+
closePicker();
|
|
3792
|
+
renderSyncStatus(res.sync || {});
|
|
3793
|
+
clearConfigCache();
|
|
3794
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
3795
|
+
Object.assign(config, await getConfig(true));
|
|
3796
|
+
refreshRows();
|
|
3797
|
+
renderToolbarSwitch();
|
|
3798
|
+
const names = (res.applied || []).map((k) => k === "model" ? L.syncIncludeModel : L.syncIncludeZcp).join(isZhLocale() ? "\u3001" : ", ");
|
|
3799
|
+
showToast(names ? `${L.syncDownloaded}\uFF08${names}\uFF09` : L.syncDownloaded, "success");
|
|
3800
|
+
};
|
|
3801
|
+
const confirmDelete = (f, rowBtns, isLatest) => {
|
|
3802
|
+
openDialog({
|
|
3803
|
+
title: L.syncVerDeleteTitle,
|
|
3804
|
+
width: "sm:max-w-md",
|
|
3805
|
+
onMount: ({ body: confirmBody, close: closeConfirm }) => {
|
|
3806
|
+
confirmBody.append(
|
|
3807
|
+
h(
|
|
3808
|
+
"p",
|
|
3809
|
+
{ class: "text-ui-sm/relaxed text-foreground-subtle" },
|
|
3810
|
+
L.syncVerDeleteDesc,
|
|
3811
|
+
h("span", { class: "font-mono" }, f.name)
|
|
3812
|
+
),
|
|
3813
|
+
...isLatest ? [h("p", { class: "mt-2 text-ui-xs/relaxed text-amber-500" }, L.syncVerDeleteLatestNote)] : [],
|
|
3814
|
+
dialogFooter(
|
|
3815
|
+
btnSecondary(L.cancel, () => closeConfirm()),
|
|
3816
|
+
btnPrimary(L.syncVerDelete, () => {
|
|
3817
|
+
closeConfirm();
|
|
3818
|
+
void deleteVersion(f, rowBtns);
|
|
3819
|
+
}, "min-w-24")
|
|
3820
|
+
)
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3823
|
+
});
|
|
3824
|
+
};
|
|
3825
|
+
const deleteVersion = async (f, rowBtns) => {
|
|
3826
|
+
setRowBusy(rowBtns, true);
|
|
3827
|
+
const res = await rpc("/sync/version/delete", { method: "POST", body: { file: f.name } });
|
|
3828
|
+
setRowBusy(rowBtns, false);
|
|
3829
|
+
if (!res.ok) {
|
|
3830
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3831
|
+
return;
|
|
3832
|
+
}
|
|
3833
|
+
showToast(L.syncVerDeleted, "success");
|
|
3834
|
+
void loadList();
|
|
3835
|
+
};
|
|
3836
|
+
const exportVersion = async (f, rowBtns, saveBtn) => {
|
|
3837
|
+
setRowBusy(rowBtns, true);
|
|
3838
|
+
saveBtn.textContent = L.syncVerSaving;
|
|
3839
|
+
const res = await rpc("/sync/version/export", { method: "POST", body: { file: f.name } });
|
|
3840
|
+
setRowBusy(rowBtns, false);
|
|
3841
|
+
saveBtn.textContent = L.syncVerSave;
|
|
3842
|
+
if (!res.ok) {
|
|
3843
|
+
if (res.code !== "export-cancelled") showToast(L.failed + ": " + errText(res), "error");
|
|
3844
|
+
return;
|
|
3845
|
+
}
|
|
3846
|
+
showToast(`${L.syncVerSaved} ${res.path}`, "success");
|
|
3847
|
+
};
|
|
3848
|
+
void loadList();
|
|
3480
3849
|
}
|
|
3481
3850
|
});
|
|
3482
3851
|
};
|
|
3483
|
-
const
|
|
3852
|
+
const runSyncPush = async () => {
|
|
3484
3853
|
syncUploadBtn.disabled = true;
|
|
3485
3854
|
syncDownloadBtn.disabled = true;
|
|
3486
|
-
const
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
const res = await rpc("/sync/run", { method: "POST", body: { direction } });
|
|
3855
|
+
const idleText = syncUploadBtn.textContent;
|
|
3856
|
+
syncUploadBtn.textContent = L.syncUploading;
|
|
3857
|
+
const res = await rpc("/sync/run", { method: "POST", body: { direction: "push" } });
|
|
3490
3858
|
syncUploadBtn.disabled = false;
|
|
3491
3859
|
syncDownloadBtn.disabled = false;
|
|
3492
|
-
|
|
3860
|
+
syncUploadBtn.textContent = idleText;
|
|
3493
3861
|
if (!res.ok) {
|
|
3494
3862
|
showToast(L.failed + ": " + errText(res), "error");
|
|
3495
3863
|
return;
|
|
3496
3864
|
}
|
|
3497
3865
|
renderSyncStatus(res.sync || {});
|
|
3498
|
-
|
|
3499
|
-
clearConfigCache();
|
|
3500
|
-
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
3501
|
-
Object.assign(config, await getConfig(true));
|
|
3502
|
-
refreshRows();
|
|
3503
|
-
renderToolbarSwitch();
|
|
3504
|
-
}
|
|
3505
|
-
if (direction === "push") showToast(L.syncUploaded, "success");
|
|
3506
|
-
else {
|
|
3507
|
-
const names = (res.applied || []).map((k) => k === "model" ? L.syncIncludeModel : L.syncIncludeZcp).join(isZhLocale() ? "\u3001" : ", ");
|
|
3508
|
-
showToast(names ? `${L.syncDownloaded}\uFF08${names}\uFF09` : L.syncDownloaded, "success");
|
|
3509
|
-
}
|
|
3866
|
+
showToast(L.syncUploaded, "success");
|
|
3510
3867
|
};
|
|
3511
3868
|
paneSync.append(
|
|
3512
3869
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncDesc),
|
|
@@ -3526,9 +3883,10 @@
|
|
|
3526
3883
|
h("p", { class: "text-ui-xs/relaxed text-foreground-subtle" }, L.syncFormHint),
|
|
3527
3884
|
syncRecLine
|
|
3528
3885
|
),
|
|
3529
|
-
syncSaveBtn
|
|
3886
|
+
h("div", { class: "flex shrink-0 items-center gap-1.5" }, syncSaveBtn, syncTestBtn)
|
|
3530
3887
|
)
|
|
3531
3888
|
),
|
|
3889
|
+
syncTestState,
|
|
3532
3890
|
h("div", { class: "mt-2 divide-y divide-border rounded-xl border border-border" }, syncIncludeWrap),
|
|
3533
3891
|
h(
|
|
3534
3892
|
"div",
|
|
@@ -3538,6 +3896,59 @@
|
|
|
3538
3896
|
),
|
|
3539
3897
|
h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" }, L.syncHint)
|
|
3540
3898
|
);
|
|
3899
|
+
const persistDevMode = async (v) => {
|
|
3900
|
+
const res = await rpc("/config", { method: "POST", body: { devMode: v } });
|
|
3901
|
+
if (!res.ok) {
|
|
3902
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3903
|
+
return false;
|
|
3904
|
+
}
|
|
3905
|
+
if (res.config) config.devMode = res.config.devMode;
|
|
3906
|
+
return true;
|
|
3907
|
+
};
|
|
3908
|
+
const devReloadBtn = btnSmall(L.devReload, () => {
|
|
3909
|
+
void runDevReload();
|
|
3910
|
+
}, "shrink-0", "primary");
|
|
3911
|
+
const runDevReload = async () => {
|
|
3912
|
+
devReloadBtn.disabled = true;
|
|
3913
|
+
devReloadBtn.textContent = L.devReloading;
|
|
3914
|
+
try {
|
|
3915
|
+
await rpc("/dev/reload", { method: "POST", body: {} });
|
|
3916
|
+
} catch {
|
|
3917
|
+
}
|
|
3918
|
+
setTimeout(() => {
|
|
3919
|
+
try {
|
|
3920
|
+
location.reload();
|
|
3921
|
+
} catch {
|
|
3922
|
+
}
|
|
3923
|
+
}, 2e3);
|
|
3924
|
+
};
|
|
3925
|
+
const devModeWrap = h("div");
|
|
3926
|
+
const renderDevPane = () => {
|
|
3927
|
+
const dev = config.devMode === true;
|
|
3928
|
+
devModeWrap.replaceChildren(
|
|
3929
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.devModeDesc),
|
|
3930
|
+
h(
|
|
3931
|
+
"div",
|
|
3932
|
+
{ class: "mt-3 divide-y divide-border rounded-xl border border-border" },
|
|
3933
|
+
settingRow(L.devMode, L.devModeRowDesc, dev, async () => {
|
|
3934
|
+
if (await persistDevMode(!dev)) renderDevPane();
|
|
3935
|
+
}),
|
|
3936
|
+
...dev ? [h(
|
|
3937
|
+
"div",
|
|
3938
|
+
{ class: "flex items-center justify-between gap-2 px-2 py-1.5" },
|
|
3939
|
+
h(
|
|
3940
|
+
"div",
|
|
3941
|
+
{ class: "min-w-0" },
|
|
3942
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.devReload),
|
|
3943
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" }, L.devReloadDesc)
|
|
3944
|
+
),
|
|
3945
|
+
devReloadBtn
|
|
3946
|
+
)] : []
|
|
3947
|
+
)
|
|
3948
|
+
);
|
|
3949
|
+
};
|
|
3950
|
+
renderDevPane();
|
|
3951
|
+
paneDebug.append(devModeWrap);
|
|
3541
3952
|
const VISION_DEFAULT_PROMPT = "\u8BF7\u8BE6\u7EC6\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5168\u90E8\u5185\u5BB9\u3002\u82E5\u662F\u754C\u9762\u6216\u56FE\u8868\u622A\u56FE\uFF0C\u8BF7\u5148\u628A\u6240\u6709\u9519\u8BEF\u3001\u8B66\u544A\u3001\u5F02\u5E38\u72B6\u6001\u9010\u5B57\u5F15\u7528\u51FA\u6765\uFF08\u542B\u5B8C\u6574\u539F\u6587\uFF09\uFF0C\u518D\u63CF\u8FF0\u6574\u4F53\u5E03\u5C40\u3001\u6587\u5B57\u4E0E\u5173\u952E\u6570\u636E\u3002";
|
|
3542
3953
|
const VISION_DEFAULT_CFG = {
|
|
3543
3954
|
enabled: true,
|
|
@@ -3575,7 +3986,57 @@
|
|
|
3575
3986
|
style: "display:none"
|
|
3576
3987
|
});
|
|
3577
3988
|
const visionInputCls = "h-8 w-full rounded-lg border border-border bg-input px-2.5 text-ui-sm text-foreground outline-none transition-shadow placeholder:text-foreground-subtle focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40";
|
|
3989
|
+
const pluginInstallCard = (pluginName, onInstalled) => {
|
|
3990
|
+
const installBtn = btnSmall(L.headroomInstall, () => {
|
|
3991
|
+
void runInstall();
|
|
3992
|
+
}, "shrink-0");
|
|
3993
|
+
const installState = h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" });
|
|
3994
|
+
const runInstall = async () => {
|
|
3995
|
+
installBtn.disabled = true;
|
|
3996
|
+
installBtn.textContent = L.headroomInstalling;
|
|
3997
|
+
installState.textContent = "";
|
|
3998
|
+
const res = await rpc("/plugins/update", { method: "POST", body: { name: pluginName } });
|
|
3999
|
+
if (!res.ok) {
|
|
4000
|
+
installBtn.disabled = false;
|
|
4001
|
+
installBtn.textContent = L.headroomInstall;
|
|
4002
|
+
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
if (onInstalled) await onInstalled();
|
|
4006
|
+
showToast(L.pluginInstallDone.replaceAll("{name}", pluginName), "success");
|
|
4007
|
+
};
|
|
4008
|
+
return h(
|
|
4009
|
+
"div",
|
|
4010
|
+
{ class: "mt-3 flex items-center justify-between gap-2 rounded-xl border border-border p-2" },
|
|
4011
|
+
h(
|
|
4012
|
+
"div",
|
|
4013
|
+
{ class: "min-w-0" },
|
|
4014
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.pluginInstallCardTitle.replaceAll("{name}", pluginName)),
|
|
4015
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" }, L.pluginInstallCardDesc),
|
|
4016
|
+
installState
|
|
4017
|
+
),
|
|
4018
|
+
installBtn
|
|
4019
|
+
);
|
|
4020
|
+
};
|
|
3578
4021
|
const renderVision = () => {
|
|
4022
|
+
if (!visionRes.ok) {
|
|
4023
|
+
paneVision.replaceChildren(
|
|
4024
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
4025
|
+
h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.visionLoadFailed + ": " + errText(visionRes))
|
|
4026
|
+
);
|
|
4027
|
+
return;
|
|
4028
|
+
}
|
|
4029
|
+
if (!visionRes.hook) {
|
|
4030
|
+
paneVision.replaceChildren(
|
|
4031
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
4032
|
+
pluginInstallCard("zcode-vision", async () => {
|
|
4033
|
+
const meta = await rpc("/vision");
|
|
4034
|
+
if (meta.ok) Object.assign(visionRes, meta);
|
|
4035
|
+
renderVision();
|
|
4036
|
+
})
|
|
4037
|
+
);
|
|
4038
|
+
return;
|
|
4039
|
+
}
|
|
3579
4040
|
if (!visionCfg) {
|
|
3580
4041
|
const initBtn = btnSmall(L.visionAddProxy, async () => {
|
|
3581
4042
|
const res = await rpc("/vision", { method: "POST", body: { config: VISION_DEFAULT_CFG } });
|
|
@@ -3587,6 +4048,16 @@
|
|
|
3587
4048
|
paneVision.replaceChildren(
|
|
3588
4049
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
3589
4050
|
...visionRes.ok ? [] : [h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.visionLoadFailed + ": " + errText(visionRes))],
|
|
4051
|
+
// 信息卡(仅版本行;配置未建,启用开关随配置出现)
|
|
4052
|
+
h(
|
|
4053
|
+
"div",
|
|
4054
|
+
{ class: "mt-3 rounded-xl border border-border p-2" },
|
|
4055
|
+
h(
|
|
4056
|
+
"div",
|
|
4057
|
+
{ class: "flex flex-wrap items-center gap-2" },
|
|
4058
|
+
h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" }, `\u63D2\u4EF6 ${visionRes.pluginVersion || "\u2014"}`)
|
|
4059
|
+
)
|
|
4060
|
+
),
|
|
3590
4061
|
h("div", { class: "mt-3 flex justify-end" }, initBtn)
|
|
3591
4062
|
);
|
|
3592
4063
|
return;
|
|
@@ -3759,7 +4230,26 @@
|
|
|
3759
4230
|
});
|
|
3760
4231
|
paneVision.replaceChildren(
|
|
3761
4232
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
3762
|
-
//
|
|
4233
|
+
// 信息卡:插件版本 + 启用图片识别开关(与 rtk/headroom 面板同款式)
|
|
4234
|
+
h(
|
|
4235
|
+
"div",
|
|
4236
|
+
{ class: "mt-3 rounded-xl border border-border p-2" },
|
|
4237
|
+
h(
|
|
4238
|
+
"div",
|
|
4239
|
+
{ class: "flex flex-wrap items-center gap-2" },
|
|
4240
|
+
h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" }, `\u63D2\u4EF6 ${visionRes.pluginVersion || "\u2014"}`),
|
|
4241
|
+
h(
|
|
4242
|
+
"div",
|
|
4243
|
+
{ class: "ml-auto" },
|
|
4244
|
+
settingRow(L.visionEnabled, "", visionCfg.enabled !== false, async () => {
|
|
4245
|
+
visionCfg.enabled = !(visionCfg.enabled !== false);
|
|
4246
|
+
await persistVision();
|
|
4247
|
+
renderVision();
|
|
4248
|
+
})
|
|
4249
|
+
)
|
|
4250
|
+
)
|
|
4251
|
+
),
|
|
4252
|
+
// 链模式 + 强制拦截开关合到一行(启用开关已上移信息卡)
|
|
3763
4253
|
h(
|
|
3764
4254
|
"div",
|
|
3765
4255
|
{ class: "mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5 rounded-xl border border-border p-1" },
|
|
@@ -3769,11 +4259,6 @@
|
|
|
3769
4259
|
h(
|
|
3770
4260
|
"div",
|
|
3771
4261
|
{ class: "ml-auto flex items-center gap-4" },
|
|
3772
|
-
settingRow(L.visionEnabled, "", visionCfg.enabled !== false, async () => {
|
|
3773
|
-
visionCfg.enabled = !(visionCfg.enabled !== false);
|
|
3774
|
-
await persistVision();
|
|
3775
|
-
renderVision();
|
|
3776
|
-
}),
|
|
3777
4262
|
settingRow(L.visionForceIntercept, "", visionCfg.forceIntercept !== false, async () => {
|
|
3778
4263
|
visionCfg.forceIntercept = !(visionCfg.forceIntercept !== false);
|
|
3779
4264
|
await persistVision();
|
|
@@ -3855,13 +4340,16 @@
|
|
|
3855
4340
|
};
|
|
3856
4341
|
const rtkInputCls = "h-8 w-full rounded-lg border border-border bg-input px-2.5 text-ui-sm text-foreground outline-none transition-shadow placeholder:text-foreground-subtle focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40";
|
|
3857
4342
|
const rtkVersionLine = h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" });
|
|
4343
|
+
let rtkLocText = "";
|
|
3858
4344
|
const renderRtkVersion = (meta) => {
|
|
3859
|
-
const v = meta.version || "rtk";
|
|
3860
|
-
rtkVersionLine.textContent = meta.
|
|
4345
|
+
const v = String(meta.version || "").replace(/^rtk\s+/i, "").trim();
|
|
4346
|
+
rtkVersionLine.textContent = `\u63D2\u4EF6 ${meta.pluginVersion || "\u2014"}${v ? ` \xB7 rtk ${v}` : ""}`;
|
|
4347
|
+
rtkLocText = meta.binPath || "";
|
|
3861
4348
|
};
|
|
3862
4349
|
renderRtkVersion(rtkRes);
|
|
3863
4350
|
const rtkUp = makeUpgradeControls({
|
|
3864
4351
|
endpoint: "/rtk",
|
|
4352
|
+
idleText: () => rtkLocText,
|
|
3865
4353
|
metaRefresh: async () => {
|
|
3866
4354
|
const meta = await rpc("/rtk");
|
|
3867
4355
|
if (meta.ok) {
|
|
@@ -3874,19 +4362,49 @@
|
|
|
3874
4362
|
const rtkSwitchRow = h("div");
|
|
3875
4363
|
const rtkVersionCard = h(
|
|
3876
4364
|
"div",
|
|
3877
|
-
{ class: "mt-3 flex items-center gap-2 rounded-xl border border-border p-2" },
|
|
4365
|
+
{ class: "mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border p-2" },
|
|
3878
4366
|
rtkVersionLine,
|
|
3879
4367
|
rtkUp.state,
|
|
3880
4368
|
rtkUp.btn,
|
|
3881
|
-
rtkSwitchRow
|
|
4369
|
+
h("div", { class: "ml-auto shrink-0" }, rtkSwitchRow)
|
|
3882
4370
|
);
|
|
3883
4371
|
const rtkBody = h("div");
|
|
4372
|
+
const rtkPluginRow = h("div");
|
|
4373
|
+
const renderRtkPluginRow = () => {
|
|
4374
|
+
rtkPluginRow.replaceChildren(...rtkRes.hook ? [] : [
|
|
4375
|
+
pluginInstallCard("rtk", async () => {
|
|
4376
|
+
const meta = await rpc("/rtk");
|
|
4377
|
+
if (meta.ok) {
|
|
4378
|
+
Object.assign(rtkRes, meta);
|
|
4379
|
+
renderRtkVersion(meta);
|
|
4380
|
+
rtkCfg = {
|
|
4381
|
+
installed: meta.installed !== false,
|
|
4382
|
+
version: meta.version || "",
|
|
4383
|
+
binPath: meta.binPath || "",
|
|
4384
|
+
mode: meta.mode === "off" ? "off" : "hint",
|
|
4385
|
+
whitelist: Array.isArray(meta.whitelist) ? [...meta.whitelist] : [],
|
|
4386
|
+
builtinGit: Array.isArray(meta.builtinGit) ? [...meta.builtinGit] : [],
|
|
4387
|
+
builtinPlain: Array.isArray(meta.builtinPlain) ? [...meta.builtinPlain] : []
|
|
4388
|
+
};
|
|
4389
|
+
}
|
|
4390
|
+
renderRtkPluginRow();
|
|
4391
|
+
renderRtk();
|
|
4392
|
+
})
|
|
4393
|
+
]);
|
|
4394
|
+
};
|
|
4395
|
+
renderRtkPluginRow();
|
|
3884
4396
|
paneRtk.append(
|
|
3885
4397
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.rtkDesc),
|
|
4398
|
+
rtkPluginRow,
|
|
3886
4399
|
rtkVersionCard,
|
|
3887
4400
|
rtkBody
|
|
3888
4401
|
);
|
|
3889
4402
|
const renderRtk = () => {
|
|
4403
|
+
if (rtkRes.ok && !rtkRes.hook) {
|
|
4404
|
+
rtkVersionCard.style.display = "none";
|
|
4405
|
+
rtkBody.replaceChildren();
|
|
4406
|
+
return;
|
|
4407
|
+
}
|
|
3890
4408
|
rtkVersionCard.style.display = rtkCfg && rtkCfg.installed ? "" : "none";
|
|
3891
4409
|
if (!rtkCfg) {
|
|
3892
4410
|
rtkBody.replaceChildren(
|
|
@@ -3932,7 +4450,55 @@
|
|
|
3932
4450
|
})
|
|
3933
4451
|
);
|
|
3934
4452
|
rtkBody.replaceChildren(
|
|
3935
|
-
...rtkCfg.installed ? [] : [h(
|
|
4453
|
+
...rtkCfg.installed ? [] : [h(
|
|
4454
|
+
"div",
|
|
4455
|
+
{ class: "flex items-center gap-2" },
|
|
4456
|
+
h("p", { class: "min-w-0 flex-1 text-ui-sm text-amber-500" }, L.rtkNotInstalled),
|
|
4457
|
+
// 一键安装本体:与“检查更新”同一条 helper 升级管线(未装则装到 ~/.local/bin)
|
|
4458
|
+
(() => {
|
|
4459
|
+
const b = btnSmall(L.rtkInstallBin, () => {
|
|
4460
|
+
void run();
|
|
4461
|
+
}, "shrink-0");
|
|
4462
|
+
const run = async () => {
|
|
4463
|
+
b.disabled = true;
|
|
4464
|
+
b.textContent = L.headroomInstalling;
|
|
4465
|
+
const res = await rpc("/rtk", { method: "POST", body: { upgrade: true } });
|
|
4466
|
+
if (!res.ok) {
|
|
4467
|
+
b.disabled = false;
|
|
4468
|
+
b.textContent = L.rtkInstallBin;
|
|
4469
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4470
|
+
return;
|
|
4471
|
+
}
|
|
4472
|
+
const done = await new Promise((resolve) => {
|
|
4473
|
+
const iv = setInterval(async () => {
|
|
4474
|
+
const s = await rpc("/rtk/upgrade");
|
|
4475
|
+
if (s.ok && s.upgrade && !s.upgrade.running) {
|
|
4476
|
+
clearInterval(iv);
|
|
4477
|
+
resolve(s.upgrade);
|
|
4478
|
+
}
|
|
4479
|
+
}, 1200);
|
|
4480
|
+
setTimeout(() => {
|
|
4481
|
+
clearInterval(iv);
|
|
4482
|
+
resolve(null);
|
|
4483
|
+
}, 10 * 60 * 1e3);
|
|
4484
|
+
});
|
|
4485
|
+
if (done && !done.error && done.version) {
|
|
4486
|
+
const meta = await rpc("/rtk");
|
|
4487
|
+
if (meta.ok) {
|
|
4488
|
+
Object.assign(rtkRes, meta);
|
|
4489
|
+
rtkCfg = { ...rtkCfg, installed: meta.installed !== false, version: meta.version || "", binPath: meta.binPath || "" };
|
|
4490
|
+
}
|
|
4491
|
+
showToast(L.rtkBinInstalled, "success");
|
|
4492
|
+
renderRtk();
|
|
4493
|
+
} else {
|
|
4494
|
+
b.disabled = false;
|
|
4495
|
+
b.textContent = L.rtkInstallBin;
|
|
4496
|
+
showToast(done && done.error || L.headroomInstallRetry, "error");
|
|
4497
|
+
}
|
|
4498
|
+
};
|
|
4499
|
+
return b;
|
|
4500
|
+
})()
|
|
4501
|
+
)],
|
|
3936
4502
|
h(
|
|
3937
4503
|
"div",
|
|
3938
4504
|
{ class: "mt-2 rounded-xl border border-border p-2" },
|
|
@@ -3989,15 +4555,16 @@
|
|
|
3989
4555
|
};
|
|
3990
4556
|
renderRtk();
|
|
3991
4557
|
const hrVersionLine = h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" });
|
|
4558
|
+
let hrLocText = "";
|
|
4559
|
+
const hrSwitchRow = h("div");
|
|
3992
4560
|
const renderHrVersion = (meta) => {
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
if (meta.version) parts.push(`${L.headroomVersionBin} ${meta.version}`);
|
|
3996
|
-
hrVersionLine.textContent = parts.length ? parts.join(" \xB7 ") : `${L.headroomVersionPlugin} \u2014`;
|
|
4561
|
+
hrVersionLine.textContent = `\u63D2\u4EF6 ${meta.pluginVersion || "\u2014"}${meta.version ? ` \xB7 headroom ${meta.version}` : ""}`;
|
|
4562
|
+
hrLocText = meta.binPath || "";
|
|
3997
4563
|
};
|
|
3998
4564
|
renderHrVersion(headroomRes);
|
|
3999
4565
|
const hrUp = makeUpgradeControls({
|
|
4000
4566
|
endpoint: "/headroom",
|
|
4567
|
+
idleText: () => hrLocText,
|
|
4001
4568
|
metaRefresh: async () => {
|
|
4002
4569
|
const meta = await rpc("/headroom");
|
|
4003
4570
|
if (meta.ok) {
|
|
@@ -4025,7 +4592,7 @@
|
|
|
4025
4592
|
installBtn.disabled = true;
|
|
4026
4593
|
installBtn.textContent = L.headroomInstalling;
|
|
4027
4594
|
installState.textContent = "";
|
|
4028
|
-
const res = await rpc("/plugins/update", { method: "POST", body: { name: "headroom"
|
|
4595
|
+
const res = await rpc("/plugins/update", { method: "POST", body: { name: "headroom" } });
|
|
4029
4596
|
if (!res.ok) {
|
|
4030
4597
|
installBtn.disabled = false;
|
|
4031
4598
|
installBtn.textContent = L.headroomInstall;
|
|
@@ -4036,6 +4603,7 @@
|
|
|
4036
4603
|
if (meta.ok) Object.assign(headroomRes, meta);
|
|
4037
4604
|
if (headroomRes.hook) {
|
|
4038
4605
|
showToast(L.headroomInstalled, "success");
|
|
4606
|
+
renderHrVersion(headroomRes);
|
|
4039
4607
|
renderHeadroomPane();
|
|
4040
4608
|
} else {
|
|
4041
4609
|
installBtn.disabled = false;
|
|
@@ -4065,17 +4633,60 @@
|
|
|
4065
4633
|
const hrRun = async (reqBody, warn) => {
|
|
4066
4634
|
if (hrBusy) return false;
|
|
4067
4635
|
hrBusy = true;
|
|
4068
|
-
const
|
|
4069
|
-
|
|
4636
|
+
const action = reqBody && reqBody.action;
|
|
4637
|
+
const isStart = action === "start" || action === "restart";
|
|
4638
|
+
const isStop = action === "stop";
|
|
4639
|
+
const rpcDone = rpc("/headroom", { method: "POST", body: reqBody });
|
|
4640
|
+
let timerIv = null;
|
|
4641
|
+
if (isStart || isStop) {
|
|
4642
|
+
const wantUp = isStart;
|
|
4643
|
+
const msg = action === "restart" ? L.hrRestarting : isStart ? L.hrStarting : L.hrStopping;
|
|
4644
|
+
const doneMsg = isStart ? L.hrStarted : L.hrStopped;
|
|
4645
|
+
const timeoutMs = isStart ? 90 * 1e3 : 30 * 1e3;
|
|
4646
|
+
const t0 = Date.now();
|
|
4647
|
+
const timerSpan = h("span", { class: "text-ui-sm text-foreground-subtle/70" }, msg + " (0s)");
|
|
4648
|
+
hrStatusLine.replaceChildren(timerSpan);
|
|
4649
|
+
timerIv = setInterval(() => {
|
|
4650
|
+
timerSpan.textContent = msg + ` (${Math.round((Date.now() - t0) / 1e3)}s)`;
|
|
4651
|
+
}, 1e3);
|
|
4652
|
+
void (async () => {
|
|
4653
|
+
const kick = await rpcDone;
|
|
4654
|
+
if (!kick.ok) return;
|
|
4655
|
+
while (Date.now() - t0 < timeoutMs) {
|
|
4656
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4657
|
+
const st = await rpc("/headroom/status");
|
|
4658
|
+
if (!st.ok) continue;
|
|
4659
|
+
const up = !!(st.status && st.status.up);
|
|
4660
|
+
if (up === wantUp) {
|
|
4661
|
+
clearInterval(timerIv);
|
|
4662
|
+
hrBusy = false;
|
|
4663
|
+
await hrRefresh();
|
|
4664
|
+
showToast(doneMsg, isStart ? "success" : void 0);
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
clearInterval(timerIv);
|
|
4669
|
+
hrBusy = false;
|
|
4670
|
+
if (isStart) showToast(L.hrStartTimeout, "error");
|
|
4671
|
+
void hrRefresh();
|
|
4672
|
+
})();
|
|
4673
|
+
}
|
|
4674
|
+
const res = await rpcDone;
|
|
4070
4675
|
if (!res.ok) {
|
|
4676
|
+
if (timerIv) clearInterval(timerIv);
|
|
4677
|
+
hrBusy = false;
|
|
4071
4678
|
showToast(L.failed + ": " + errText(res), "error");
|
|
4679
|
+
void hrRefresh();
|
|
4072
4680
|
return false;
|
|
4073
4681
|
}
|
|
4074
4682
|
if (res.config) Object.assign(hrCfg, res.config);
|
|
4075
4683
|
if (warn) showToast(warn);
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4684
|
+
if (!isStart && !isStop) {
|
|
4685
|
+
hrBusy = false;
|
|
4686
|
+
setTimeout(() => {
|
|
4687
|
+
void hrRefresh();
|
|
4688
|
+
}, 1200);
|
|
4689
|
+
}
|
|
4079
4690
|
return true;
|
|
4080
4691
|
};
|
|
4081
4692
|
const hrDevLabel = (v) => v == null ? "\u2014" : v === "auto" ? L.hrValAuto : v === "cpu" ? "CPU" : v;
|
|
@@ -4120,6 +4731,23 @@
|
|
|
4120
4731
|
hrHintLine.textContent = s.saverHint || "";
|
|
4121
4732
|
hrHintLine.style.display = s.saverHint ? "" : "none";
|
|
4122
4733
|
};
|
|
4734
|
+
const renderHrUsageSwitch = () => {
|
|
4735
|
+
const usageOn = !!(headroomRes.usage && headroomRes.usage.enabled);
|
|
4736
|
+
hrSwitchRow.replaceChildren(
|
|
4737
|
+
settingRow(L.pluginEnable, "", usageOn, async () => {
|
|
4738
|
+
const next = !usageOn;
|
|
4739
|
+
const res = await rpc("/headroom", { method: "POST", body: { usage: next } });
|
|
4740
|
+
if (!res.ok) {
|
|
4741
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4742
|
+
return;
|
|
4743
|
+
}
|
|
4744
|
+
if (res.usage) headroomRes.usage = res.usage;
|
|
4745
|
+
renderHrUsageSwitch();
|
|
4746
|
+
if (next && !res.changed && !(res.usage && res.usage.enabled)) showToast(L.hrUsageNone);
|
|
4747
|
+
})
|
|
4748
|
+
);
|
|
4749
|
+
};
|
|
4750
|
+
renderHrUsageSwitch();
|
|
4123
4751
|
const hrRefreshBtn = btnSmall(L.headroomRefresh, () => {
|
|
4124
4752
|
void hrRefresh();
|
|
4125
4753
|
});
|
|
@@ -4212,14 +4840,69 @@
|
|
|
4212
4840
|
hrPwrHint.style.display = hrCfg.kompressBackend === "cpu" ? "" : "none";
|
|
4213
4841
|
};
|
|
4214
4842
|
updateHrPwrHint();
|
|
4843
|
+
const hrInstallBinBtn = (() => {
|
|
4844
|
+
const b = btnSmall(L.hrInstallBin, () => {
|
|
4845
|
+
void run();
|
|
4846
|
+
}, "shrink-0");
|
|
4847
|
+
let busy = false;
|
|
4848
|
+
const run = async () => {
|
|
4849
|
+
if (busy) return;
|
|
4850
|
+
busy = true;
|
|
4851
|
+
b.disabled = true;
|
|
4852
|
+
b.textContent = L.headroomInstalling;
|
|
4853
|
+
const res = await rpc("/headroom", { method: "POST", body: { upgrade: true } });
|
|
4854
|
+
if (!res.ok) {
|
|
4855
|
+
b.disabled = false;
|
|
4856
|
+
b.textContent = L.hrInstallBin;
|
|
4857
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4858
|
+
busy = false;
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
const done = await new Promise((resolve) => {
|
|
4862
|
+
const iv = setInterval(async () => {
|
|
4863
|
+
const s = await rpc("/headroom/upgrade");
|
|
4864
|
+
if (s.ok && s.upgrade && !s.upgrade.running) {
|
|
4865
|
+
clearInterval(iv);
|
|
4866
|
+
resolve(s.upgrade);
|
|
4867
|
+
}
|
|
4868
|
+
}, 2e3);
|
|
4869
|
+
setTimeout(() => {
|
|
4870
|
+
clearInterval(iv);
|
|
4871
|
+
resolve(null);
|
|
4872
|
+
}, 12 * 60 * 1e3);
|
|
4873
|
+
});
|
|
4874
|
+
busy = false;
|
|
4875
|
+
if (done && !done.error && done.version) {
|
|
4876
|
+
const meta = await rpc("/headroom");
|
|
4877
|
+
if (meta.ok) {
|
|
4878
|
+
renderHrVersion(meta);
|
|
4879
|
+
Object.assign(headroomRes, meta);
|
|
4880
|
+
}
|
|
4881
|
+
showToast(L.hrBinInstalled, "success");
|
|
4882
|
+
renderHeadroomPane();
|
|
4883
|
+
} else {
|
|
4884
|
+
b.disabled = false;
|
|
4885
|
+
b.textContent = L.hrInstallBin;
|
|
4886
|
+
showToast(done && done.error || L.headroomInstallRetry, "error");
|
|
4887
|
+
}
|
|
4888
|
+
};
|
|
4889
|
+
return b;
|
|
4890
|
+
})();
|
|
4215
4891
|
paneHeadroom.append(
|
|
4216
4892
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.headroomDesc),
|
|
4217
|
-
...headroomRes.installed === false ? [h(
|
|
4893
|
+
...headroomRes.installed === false ? [h(
|
|
4894
|
+
"div",
|
|
4895
|
+
{ class: "mt-2 flex items-center gap-2" },
|
|
4896
|
+
h("p", { class: "min-w-0 flex-1 text-ui-sm text-amber-500" }, L.headroomBinMissing),
|
|
4897
|
+
hrInstallBinBtn
|
|
4898
|
+
)] : [],
|
|
4218
4899
|
h(
|
|
4219
4900
|
"div",
|
|
4220
|
-
{ class: "mt-3 flex items-center
|
|
4221
|
-
|
|
4222
|
-
hrUp.
|
|
4901
|
+
{ class: "mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border p-2" },
|
|
4902
|
+
hrVersionLine,
|
|
4903
|
+
hrUp.state,
|
|
4904
|
+
hrUp.btn,
|
|
4905
|
+
h("div", { class: "ml-auto shrink-0" }, hrSwitchRow)
|
|
4223
4906
|
),
|
|
4224
4907
|
h(
|
|
4225
4908
|
"div",
|
|
@@ -4273,7 +4956,8 @@
|
|
|
4273
4956
|
paneSync,
|
|
4274
4957
|
paneVision,
|
|
4275
4958
|
paneHeadroom,
|
|
4276
|
-
paneRtk
|
|
4959
|
+
paneRtk,
|
|
4960
|
+
paneDebug
|
|
4277
4961
|
);
|
|
4278
4962
|
}
|
|
4279
4963
|
});
|
|
@@ -5736,7 +6420,7 @@
|
|
|
5736
6420
|
if (status.updates.length === 0) return;
|
|
5737
6421
|
const config = await getConfig();
|
|
5738
6422
|
if ((config.features || {}).autoUpdatePlugins === true) {
|
|
5739
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {
|
|
6423
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
5740
6424
|
if (res.ok) showToast(L.pluginsAutoUpdated, "success");
|
|
5741
6425
|
else showToast(L.pluginsUpdateFailed + ": " + (res.error || ""), "error");
|
|
5742
6426
|
return;
|
|
@@ -5758,8 +6442,14 @@
|
|
|
5758
6442
|
// src/inject/index.js
|
|
5759
6443
|
(function zcodeproInject() {
|
|
5760
6444
|
if (typeof window === "undefined") return;
|
|
5761
|
-
if (window.__zcodeproInjected)
|
|
6445
|
+
if (window.__zcodeproInjected) {
|
|
6446
|
+
const boot = window.__ZCODEPRO__ || {};
|
|
6447
|
+
const sameGeneration = window.__zcodeproBootedToken && boot.token && window.__zcodeproBootedToken === boot.token;
|
|
6448
|
+
if (!sameGeneration) location.reload();
|
|
6449
|
+
return;
|
|
6450
|
+
}
|
|
5762
6451
|
window.__zcodeproInjected = true;
|
|
6452
|
+
window.__zcodeproBootedToken = (window.__ZCODEPRO__ || {}).token || "";
|
|
5763
6453
|
try {
|
|
5764
6454
|
startLocaleResolver();
|
|
5765
6455
|
} catch {
|