zcode-pro 0.17.2 → 0.19.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 +1 -0
- package/README.md +1 -0
- package/dist/inject.js +1368 -216
- package/package.json +1 -1
- package/src/host/helper.mjs +1248 -156
- package/src/host/main.mjs +11 -0
- package/src/host/pickFolder.mjs +48 -3
- package/src/host/setup.mjs +34 -9
- package/src/host/taskIndex.mjs +83 -0
- package/src/host/webdav.mjs +128 -12
- package/src/inject/core.js +190 -42
- package/src/inject/features/file-menu.js +9 -2
- package/src/inject/features/plugin-updates.js +1 -1
- package/src/inject/features/settings-dialog.js +821 -118
- package/src/inject/features/styles.js +15 -1
- package/src/inject/features/title-gen.js +169 -0
- package/src/inject/features/title-lock.js +14 -0
- package/src/inject/features/toolbar-icons.js +38 -4
- package/src/inject/index.js +14 -2
- package/src/inject/provider-fields.js +71 -0
- package/src/inject/ui.js +23 -7
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) }));
|
|
@@ -32,22 +35,31 @@
|
|
|
32
35
|
tabFeatures: "\u529F\u80FD",
|
|
33
36
|
tabStyles: "\u6837\u5F0F",
|
|
34
37
|
tabProxy: "\u4EE3\u7406",
|
|
38
|
+
tabBehavior: "\u884C\u4E3A",
|
|
35
39
|
tabAgents: "\u5168\u5C40\u63D0\u793A\u8BCD",
|
|
36
40
|
agentsDesc: "\u5199\u5165 ~/.zcode/AGENTS.md\uFF0C\u4F5C\u4E3A\u9ED8\u8BA4\u6307\u4EE4\u7528\u4E8E\u6240\u6709\u9879\u76EE\u7684\u6BCF\u6B21\u4F1A\u8BDD\uFF1B\u4FDD\u5B58\u540E\u4ECE\u65B0\u4F1A\u8BDD\u8D77\u751F\u6548\uFF0C\u9879\u76EE\u5185\u7684 AGENTS.md \u53EF\u8865\u5145\u6216\u8986\u76D6\u3002\u5185\u5BB9\u8D85\u8FC7 100KB \u4F1A\u88AB\u5E94\u7528\u622A\u65AD\u3002",
|
|
37
41
|
agentsPlaceholder: "\u586B\u5199\u5E0C\u671B\u6240\u6709\u9879\u76EE\u9ED8\u8BA4\u9075\u5FAA\u7684\u6307\u4EE4\uFF1B\u6E05\u7A7A\u5E76\u4FDD\u5B58\u5373\u79FB\u9664\u5168\u5C40\u63D0\u793A\u8BCD",
|
|
38
42
|
agentsSave: "\u4FDD\u5B58",
|
|
39
43
|
agentsSaved: "\u5168\u5C40\u63D0\u793A\u8BCD\u5DF2\u4FDD\u5B58",
|
|
40
44
|
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\
|
|
45
|
+
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
46
|
proxyPlaceholder: "http://127.0.0.1:7890",
|
|
43
47
|
proxySave: "\u4FDD\u5B58",
|
|
44
48
|
proxySaved: "\u4EE3\u7406\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
|
|
45
49
|
proxyHint: "\u7559\u7A7A\u4FDD\u5B58\u5373\u6E05\u9664\u4EE3\u7406\u3002",
|
|
46
50
|
proxyTest: "\u68C0\u6D4B",
|
|
47
51
|
proxyTesting: "\u68C0\u6D4B\u4E2D\u2026",
|
|
52
|
+
proxyTestEmpty: "\u8BF7\u5148\u8F93\u5165\u4EE3\u7406\u5730\u5740",
|
|
48
53
|
proxyTestFailed: "\u68C0\u6D4B\u5931\u8D25",
|
|
54
|
+
proxyScopePlugins: "\u63D2\u4EF6\u5E02\u573A\u66F4\u65B0",
|
|
55
|
+
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",
|
|
56
|
+
proxyScopeDeps: "\u63D2\u4EF6\u4F9D\u8D56\u8F6F\u4EF6",
|
|
57
|
+
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",
|
|
58
|
+
proxyScopeSync: "\u540C\u6B65",
|
|
59
|
+
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
60
|
tabSync: "\u540C\u6B65",
|
|
50
|
-
|
|
61
|
+
tabDebug: "\u8C03\u8BD5",
|
|
62
|
+
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
63
|
syncUrlPlaceholder: "https://dav.jianguoyun.com/dav/",
|
|
52
64
|
syncDir: "\u4E0A\u4F20\u76EE\u5F55",
|
|
53
65
|
syncDirPlaceholder: "zcode-pro",
|
|
@@ -55,7 +67,7 @@
|
|
|
55
67
|
syncPassword: "\u5BC6\u7801",
|
|
56
68
|
syncSave: "\u4FDD\u5B58",
|
|
57
69
|
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\
|
|
70
|
+
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
71
|
syncRecLink: "\u575A\u679C\u4E91 WebDAV",
|
|
60
72
|
syncRecSuffix: "\uFF1A\u767B\u5F55\u4E0E\u5BC6\u7801\u586B\u201C\u5E94\u7528\u5BC6\u7801\u201D\uFF0C\u4E0D\u662F\u8D26\u53F7\u5BC6\u7801\u3002",
|
|
61
73
|
syncIncludeZcp: "ZCode Pro \u8BBE\u7F6E",
|
|
@@ -65,16 +77,44 @@
|
|
|
65
77
|
syncUpload: "\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
66
78
|
syncDownload: "\u4ECE\u4E91\u7AEF\u4E0B\u8F7D",
|
|
67
79
|
syncUploading: "\u4E0A\u4F20\u4E2D\u2026",
|
|
68
|
-
syncDownloading: "\u4E0B\u8F7D\u4E2D\u2026",
|
|
69
80
|
syncUploaded: "\u5DF2\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
70
81
|
syncDownloaded: "\u5DF2\u4ECE\u4E91\u7AEF\u6062\u590D",
|
|
71
82
|
syncLastPush: "\u4E0A\u6B21\u4E0A\u4F20",
|
|
72
83
|
syncLastPull: "\u4E0A\u6B21\u4E0B\u8F7D",
|
|
73
84
|
syncNever: "\u65E0",
|
|
74
85
|
syncConfirmTitle: "\u4ECE\u4E91\u7AEF\u4E0B\u8F7D",
|
|
75
|
-
syncConfirmDesc: "\u5C06\u7528\
|
|
76
|
-
syncConfirmGo: "\u786E\u8BA4\
|
|
86
|
+
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",
|
|
87
|
+
syncConfirmGo: "\u786E\u8BA4\u5BFC\u5165",
|
|
88
|
+
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",
|
|
89
|
+
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
90
|
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",
|
|
91
|
+
syncTest: "\u6D4B\u8BD5",
|
|
92
|
+
syncTesting: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
93
|
+
syncTestEmpty: "\u8BF7\u5148\u586B\u5199 URL",
|
|
94
|
+
syncTestFailed: "\u6D4B\u8BD5\u5931\u8D25",
|
|
95
|
+
syncTestStepConnect: "\u8FDE\u63A5",
|
|
96
|
+
syncTestStepDir: "\u76EE\u5F55",
|
|
97
|
+
syncTestStepList: "\u6587\u4EF6",
|
|
98
|
+
syncTestFilesFound: "\u4E91\u7AEF\u5DF2\u6709 {n} \u4E2A\u5907\u4EFD\u6587\u4EF6",
|
|
99
|
+
syncPickTitle: "\u8BF7\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6",
|
|
100
|
+
syncPickLoading: "\u6B63\u5728\u8BFB\u53D6\u4E91\u7AEF\u6587\u4EF6\u5217\u8868\u2026",
|
|
101
|
+
syncPickEmpty: "\u4E91\u7AEF\u8FD8\u6CA1\u6709\u5907\u4EFD\u6587\u4EF6\uFF0C\u8BF7\u5148\u5728\u5176\u4ED6\u7535\u8111\u4E0A\u4F20",
|
|
102
|
+
syncVerImport: "\u5BFC\u5165",
|
|
103
|
+
syncVerImporting: "\u5BFC\u5165\u4E2D\u2026",
|
|
104
|
+
syncVerDelete: "\u5220\u9664",
|
|
105
|
+
syncVerSave: "\u4FDD\u5B58\u5230\u78C1\u76D8",
|
|
106
|
+
syncVerSaving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
107
|
+
syncVerLatest: "\u6700\u65B0",
|
|
108
|
+
syncVerDeleteTitle: "\u5220\u9664\u4E91\u7AEF\u6587\u4EF6",
|
|
109
|
+
syncVerDeleteDesc: "\u5C06\u5220\u9664\u4E91\u7AEF\u7684\u8FD9\u4EFD\u5907\u4EFD\uFF0C\u4E0D\u53EF\u6062\u590D\uFF1A",
|
|
110
|
+
syncVerDeleted: "\u5DF2\u5220\u9664\u4E91\u7AEF\u5907\u4EFD",
|
|
111
|
+
syncVerSaved: "\u5DF2\u4FDD\u5B58\u5230",
|
|
112
|
+
devMode: "\u5F00\u53D1\u6A21\u5F0F",
|
|
113
|
+
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",
|
|
114
|
+
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",
|
|
115
|
+
devReload: "\u91CD\u8F7D ZCode Pro",
|
|
116
|
+
devReloading: "\u91CD\u8F7D\u4E2D\u2026",
|
|
117
|
+
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
118
|
rowGapName: "\u6BB5\u843D\u95F4\u8DDD",
|
|
79
119
|
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
120
|
listSpacingName: "\u5217\u8868\u4E0A\u4E0B\u8FB9\u8DDD",
|
|
@@ -91,6 +131,8 @@
|
|
|
91
131
|
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
132
|
lineHeightName: "\u56DE\u7B54\u884C\u9AD8",
|
|
93
133
|
lineHeightDesc: "\u56DE\u7B54\u6B63\u6587\u7684\u884C\u9AD8\uFF08\u500D\u6570\uFF09\u3002",
|
|
134
|
+
thinkingLineHeightName: "\u601D\u8003\u884C\u9AD8",
|
|
135
|
+
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
136
|
userLineHeightName: "\u63D0\u95EE\u884C\u9AD8",
|
|
95
137
|
userLineHeightDesc: "\u63D0\u95EE\u5185\u5BB9\u7684\u884C\u9AD8\uFF08\u500D\u6570\uFF09\u3002",
|
|
96
138
|
contentWidthName: "\u5185\u5BB9\u5BBD\u5EA6",
|
|
@@ -105,6 +147,30 @@
|
|
|
105
147
|
featureSessionSwitchDesc: "alt+z \u5728\u5F53\u524D\u4E0E\u4E0A\u6B21\u4F1A\u8BDD\u95F4\u6765\u56DE\u5207\u6362\uFF1B\u6309\u4F4F alt \u518D\u6309 x/c \u5F39\u51FA\u6700\u8FD1\u4F1A\u8BDD\u5217\u8868\u524D\u540E\u9009\u62E9\uFF0C\u677E\u5F00 alt \u5207\u6362\uFF08\u7C7B alt+tab\uFF09\u3002",
|
|
106
148
|
featureTitleLock: "\u91CD\u547D\u540D\u4F1A\u8BDD\u540D\u9501\u5B9A",
|
|
107
149
|
featureTitleLockDesc: "\u624B\u52A8\u91CD\u547D\u540D\u8FC7\u7684\u4F1A\u8BDD\u4E0D\u518D\u88AB\u81EA\u52A8\u6807\u9898\u8986\u76D6\uFF1A\u4F1A\u8BDD\u6709\u65B0\u56DE\u7B54\u540E\u754C\u9762\u53EF\u80FD\u6539\u663E\u81EA\u52A8\u6807\u9898\uFF0C\u91CD\u542F\u540E\u53C8\u53D8\u56DE\uFF0C\u672C\u529F\u80FD\u8BA9\u4FA7\u680F\u59CB\u7EC8\u663E\u793A\u91CD\u547D\u540D\u540E\u7684\u540D\u5B57\u3002",
|
|
150
|
+
tabTitleGen: "\u4EFB\u52A1\u540D\u63D0\u793A\u8BCD",
|
|
151
|
+
titleGenShortDesc: "\u65B0\u4F1A\u8BDD\u5F00\u59CB\u4F5C\u7B54\u65F6\uFF0C\u6309\u6240\u9009\u4F9B\u5E94\u5546\u4E0E\u63D0\u793A\u8BCD\u751F\u6210\u4EFB\u52A1\u540D\u5E76\u6309\u624B\u52A8\u91CD\u547D\u540D\u4FDD\u5B58\uFF0C\u5B98\u65B9\u81EA\u52A8\u6807\u9898\u4E0D\u518D\u8986\u76D6\u3002",
|
|
152
|
+
titleGenEnabled: "\u542F\u7528",
|
|
153
|
+
titleGenProvider: "\u4F9B\u5E94\u5546",
|
|
154
|
+
titleGenProviderNone: "\u4E0D\u8DDF\u968F\uFF08\u81EA\u586B\u5730\u5740\uFF09",
|
|
155
|
+
titleGenProviderSession: "\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD",
|
|
156
|
+
titleGenProviderDeleted: "\uFF08\u5DF2\u5220\u9664\uFF09",
|
|
157
|
+
titleGenModel: "\u6A21\u578B",
|
|
158
|
+
titleGenModelHint: "\u4ECE\u5217\u8868\u9009\u62E9\uFF0C\u6216\u76F4\u63A5\u586B\u5199\u6A21\u578B id",
|
|
159
|
+
titleGenModelEmpty: "\uFF08\u672A\u9009\u62E9\uFF09",
|
|
160
|
+
titleGenModelSessionHint: "\u4ECE\u5217\u8868\u9009\u62E9\u6A21\u578B\uFF1B\u5217\u8868\u7B2C\u4E00\u9879\u4E3A\u8DDF\u968F\u4F1A\u8BDD\u5F53\u524D\u6A21\u578B",
|
|
161
|
+
titleGenModelFollowSession: "\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u5F53\u524D\u6A21\u578B",
|
|
162
|
+
titleGenModelManualHint: "\u8F93\u5165\u6A21\u578B id",
|
|
163
|
+
titleGenBaseUrl: "\u63A5\u53E3\u5730\u5740",
|
|
164
|
+
titleGenApiKey: "API Key",
|
|
165
|
+
titleGenFormat: "\u534F\u8BAE",
|
|
166
|
+
titleGenPrompt: "\u63D0\u793A\u8BCD",
|
|
167
|
+
titleGenPromptPlaceholder: "\u7559\u7A7A\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u63D0\u793A\u8BCD\uFF08\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u53EF\u67E5\u770B\uFF09",
|
|
168
|
+
titleGenPromptReset: "\u4F7F\u7528\u9ED8\u8BA4\u63D0\u793A\u8BCD",
|
|
169
|
+
titleGenSample: "\u6D4B\u8BD5\u6D88\u606F",
|
|
170
|
+
titleGenTest: "\u6D4B\u8BD5\u751F\u6210",
|
|
171
|
+
titleGenTesting: "\u751F\u6210\u4E2D\u2026",
|
|
172
|
+
titleGenTestOk: "\u751F\u6210\u7ED3\u679C\uFF1A",
|
|
173
|
+
titleGenTestFailed: "\u751F\u6210\u5931\u8D25",
|
|
108
174
|
featureWsRunning: "\u6298\u53E0\u9879\u76EE\u8FD0\u884C\u63D0\u793A\uFF08\u5B9E\u9A8C\u6027\uFF09",
|
|
109
175
|
featureWsRunningDesc: "\u6298\u53E0\u7684\u9879\u76EE\u91CC\u4ECD\u6709\u4F1A\u8BDD\u5728\u8FD0\u884C\u65F6\uFF0C\u9879\u76EE\u56FE\u6807\u65CB\u8F6C\u63D0\u793A\uFF1B\u5168\u90E8\u7ED3\u675F\u6216\u5C55\u5F00\u9879\u76EE\u540E\u6062\u590D\u3002\u671F\u95F4\u6BCF 60 \u79D2\u5728\u540E\u53F0\u77ED\u6682\u5C55\u5F00\u8BE5\u9879\u76EE\u590D\u6838\u8FD0\u884C\u72B6\u6001\u518D\u6536\u8D77\uFF0C\u4F1A\u8BDD\u884C\u4E0D\u663E\u793A\uFF0C\u4EC5\u9879\u76EE\u4F4D\u7F6E\u53EF\u80FD\u6709\u7EA6\u56DB\u5206\u4E4B\u4E00\u79D2\u7684\u8F7B\u5FAE\u9AD8\u5EA6\u8D77\u4F0F\u3002",
|
|
110
176
|
tabPerformance: "\u6027\u80FD",
|
|
@@ -154,7 +220,7 @@
|
|
|
154
220
|
featurePinnedExpand: "\u7F6E\u9876\u4F1A\u8BDD\u4FDD\u6301\u9879\u76EE\u6298\u53E0\uFF08\u5B9E\u9A8C\u6027\uFF09",
|
|
155
221
|
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
222
|
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\
|
|
223
|
+
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
224
|
pluginsUpdateTitle: "\u63D2\u4EF6\u66F4\u65B0 \xB7 zcode-plugins",
|
|
159
225
|
pluginsCheckNow: "\u68C0\u67E5\u5E76\u66F4\u65B0",
|
|
160
226
|
pluginsUpdating: "\u6B63\u5728\u66F4\u65B0\u63D2\u4EF6\u2026",
|
|
@@ -166,7 +232,7 @@
|
|
|
166
232
|
pluginsAutoUpdated: "zcode-plugins \u63D2\u4EF6\u5DF2\u66F4\u65B0",
|
|
167
233
|
tabVision: "Vision",
|
|
168
234
|
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
|
|
235
|
+
visionEnabled: "\u542F\u7528",
|
|
170
236
|
visionForceIntercept: "\u4E3B\u6A21\u578B\u80FD\u770B\u56FE\u4E5F\u62E6\u622A",
|
|
171
237
|
visionMode: "\u94FE\u6A21\u5F0F",
|
|
172
238
|
visionModeFallback: "\u4F9D\u6B21\u5C1D\u8BD5",
|
|
@@ -179,10 +245,6 @@
|
|
|
179
245
|
visionMoveDown: "\u4E0B\u79FB",
|
|
180
246
|
visionName: "\u540D\u79F0",
|
|
181
247
|
visionUseProvider: "\u4F9B\u5E94\u5546",
|
|
182
|
-
visionUseProviderHint: "\u4E0B\u62C9\u9009\u62E9\u6216\u624B\u52A8\u8F93\u5165\uFF1Asession=\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u4F9B\u5E94\u5546\uFF0C\u6216\u4F9B\u5E94\u5546\u540D/ID\uFF1B\u8BBE\u7F6E\u540E baseUrl/API Key/\u683C\u5F0F\u81EA\u52A8\u53D6\u8BE5\u4F9B\u5E94\u5546",
|
|
183
|
-
visionUseProviderNone: "\u4E0D\u8DDF\u968F\uFF08\u81EA\u586B\u5730\u5740\uFF09",
|
|
184
|
-
visionUseProviderSession: "\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\uFF08session\uFF09",
|
|
185
|
-
visionUseProviderUnknown: "\u672A\u627E\u5230\u8BE5\u4F9B\u5E94\u5546\uFF0C\u8BC6\u522B\u65F6\u4F1A\u62A5\u9519\uFF1B\u8BF7\u4ECE\u4E0B\u62C9\u9009\u62E9\uFF0C\u6216\u8F93\u5165 session",
|
|
186
248
|
visionSkipAfterFailures: "\u8FDE\u7EED\u5931\u8D25\u6B21\u6570",
|
|
187
249
|
visionSkipAfterFailuresHint: "\u67D0\u4EE3\u7406\u8FDE\u7EED\u5931\u8D25\u6EE1\u6B21\u6570\u540E\u6682\u65F6\u8DF3\u8FC7\u5B83\uFF0C\u76F4\u63A5\u8BD5\u4E0B\u4E00\u4E2A\uFF1B0 = \u4E0D\u8DF3\u8FC7",
|
|
188
250
|
visionSkipMinutes: "\u8DF3\u8FC7\u5206\u949F\u6570",
|
|
@@ -191,21 +253,21 @@
|
|
|
191
253
|
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
254
|
visionBaseUrl: "\u63A5\u53E3\u5730\u5740 baseUrl",
|
|
193
255
|
visionModel: "\u6A21\u578B",
|
|
194
|
-
visionFormat: "\u683C\u5F0F",
|
|
195
256
|
visionApiKey: "API Key",
|
|
196
257
|
visionApiKeyHint: "\u7559\u7A7A\u81EA\u52A8\u53D6 GLM \u8BA2\u9605 key",
|
|
197
258
|
visionPrompt: "\u8BC6\u522B\u63D0\u793A\u8BCD\uFF08pipeline \u540E\u7EED\u6B65\u53EF\u7528 {prev} \u5F15\u7528\u4E0A\u4E00\u6B65\uFF09",
|
|
198
259
|
visionTest: "\u6D4B\u8BD5",
|
|
199
260
|
visionTesting: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
200
261
|
visionTestFailed: "\u89C6\u89C9\u4EE3\u7406\u6D4B\u8BD5\u5931\u8D25",
|
|
201
|
-
visionTestOutput: "\u6D4B\u8BD5\u8F93\u51FA",
|
|
202
262
|
visionCompressKB: "\u538B\u7F29\u9608\u503C KB",
|
|
203
263
|
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
264
|
visionLoadFailed: "\u8BFB\u53D6\u89C6\u89C9\u4EE3\u7406\u914D\u7F6E\u5931\u8D25",
|
|
205
265
|
tabRtk: "rtk",
|
|
206
266
|
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\
|
|
267
|
+
rtkEnabled: "\u542F\u7528",
|
|
268
|
+
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",
|
|
269
|
+
rtkInstallBin: "\u5B89\u88C5 rtk \u672C\u4F53",
|
|
270
|
+
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
271
|
rtkWhitelistTitle: "\u767D\u540D\u5355\uFF08\u4E0D\u538B\u7F29\u76F4\u63A5\u653E\u884C\uFF09",
|
|
210
272
|
rtkBuiltinLabel: "\u5185\u7F6E\u653E\u884C\uFF08\u53EA\u8BFB\uFF0C\u968F\u63D2\u4EF6\u66F4\u65B0\uFF09\uFF1A",
|
|
211
273
|
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 +280,25 @@
|
|
|
218
280
|
tabHeadroom: "Headroom",
|
|
219
281
|
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
282
|
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",
|
|
283
|
+
hrInstallBin: "\u5B89\u88C5 headroom \u672C\u4F53",
|
|
284
|
+
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
285
|
headroomInstallTitle: "\u672A\u5B89\u88C5 headroom \u63D2\u4EF6",
|
|
222
286
|
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
287
|
headroomInstall: "\u5B89\u88C5",
|
|
224
288
|
headroomInstalling: "\u5B89\u88C5\u4E2D\u2026",
|
|
225
289
|
headroomInstalled: "\u5DF2\u5B89\u88C5 headroom \u63D2\u4EF6",
|
|
226
290
|
headroomInstallRetry: "\u5B89\u88C5\u672A\u751F\u6548\uFF0C\u8BF7\u91CD\u8BD5\u6216\u624B\u52A8\u5728\u63D2\u4EF6\u5E02\u573A\u5B89\u88C5",
|
|
291
|
+
pluginInstallCardTitle: "\u672A\u5B89\u88C5 {name} \u63D2\u4EF6",
|
|
292
|
+
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",
|
|
293
|
+
pluginInstallDone: "\u5DF2\u5B89\u88C5 {name} \u63D2\u4EF6",
|
|
294
|
+
pluginEnable: "\u542F\u7528",
|
|
295
|
+
hrStarting: "\u6B63\u5728\u542F\u52A8\u538B\u7F29\u4EE3\u7406\u2026",
|
|
296
|
+
hrStarted: "\u538B\u7F29\u4EE3\u7406\u5DF2\u542F\u52A8",
|
|
297
|
+
hrStartTimeout: "\u4EE3\u7406\u542F\u52A8\u8D85\u65F6\uFF0890 \u79D2\uFF09\uFF0C\u8BF7\u68C0\u67E5 ~/.zcode-headroom-proxy.log",
|
|
298
|
+
hrStopping: "\u6B63\u5728\u505C\u6B62\u538B\u7F29\u4EE3\u7406\u2026",
|
|
299
|
+
hrRestarting: "\u6B63\u5728\u91CD\u542F\u538B\u7F29\u4EE3\u7406\u2026",
|
|
300
|
+
hrStopped: "\u538B\u7F29\u4EE3\u7406\u5DF2\u505C\u6B62",
|
|
301
|
+
hrUsageNone: "\u5F53\u524D\u6CA1\u6709\u8D70 headroom \u7684\u4F9B\u5E94\u5546\uFF0C\u672A\u5207\u6362",
|
|
227
302
|
headroomLoadFailed: "\u8BFB\u53D6 Headroom \u914D\u7F6E\u5931\u8D25",
|
|
228
303
|
headroomStatusTitle: "\u8FD0\u884C\u72B6\u6001",
|
|
229
304
|
headroomStatusLoadFailed: "\u8BFB\u53D6\u8FD0\u884C\u72B6\u6001\u5931\u8D25",
|
|
@@ -249,7 +324,7 @@
|
|
|
249
324
|
headroomRestart: "\u91CD\u542F",
|
|
250
325
|
headroomStopAction: "\u505C\u6B62",
|
|
251
326
|
headroomStopTitle: "\u505C\u6B62 Headroom \u4EE3\u7406",
|
|
252
|
-
headroomStopDesc: "\u505C\u6B62\u540E\uFF0CZCode \u4E2D\u6307\u5411\u8BE5\u4EE3\u7406\uFF08127.0.0.1\uFF09\u7684\
|
|
327
|
+
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
328
|
headroomStoppedWarn: "\u4EE3\u7406\u5DF2\u505C\u6B62\uFF1B\u6307\u5411 127.0.0.1 \u7684\u4F9B\u5E94\u5546\u5C06\u65E0\u6CD5\u8FDE\u63A5",
|
|
254
329
|
headroomBackend: "\u538B\u7F29\u8BBE\u5907",
|
|
255
330
|
headroomBackendAuto: "\u81EA\u52A8 \xB7 \u663E\u5361\u4F18\u5148",
|
|
@@ -267,8 +342,6 @@
|
|
|
267
342
|
headroomInterval: "\u76D1\u89C6\u95F4\u9694",
|
|
268
343
|
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
344
|
headroomSecUnit: "\u79D2",
|
|
270
|
-
headroomVersionPlugin: "\u63D2\u4EF6",
|
|
271
|
-
headroomVersionBin: "\u7A0B\u5E8F",
|
|
272
345
|
upgradeCheck: "\u68C0\u67E5\u66F4\u65B0",
|
|
273
346
|
upgradeChecking: "\u68C0\u67E5\u4E2D\u2026",
|
|
274
347
|
upgradeUpToDate: "\u5DF2\u662F\u6700\u65B0\uFF08{v}\uFF09",
|
|
@@ -280,7 +353,6 @@
|
|
|
280
353
|
upgradeDone: "\u5DF2\u66F4\u65B0\u5230 {v}",
|
|
281
354
|
upgradeFinished: "\u5347\u7EA7\u5B8C\u6210",
|
|
282
355
|
upgradeCheckFailed: "\u68C0\u67E5\u66F4\u65B0\u5931\u8D25",
|
|
283
|
-
version: "\u7248\u672C",
|
|
284
356
|
close: "\u5173\u95ED",
|
|
285
357
|
cancel: "\u53D6\u6D88",
|
|
286
358
|
pathLabel: "\u8DEF\u5F84",
|
|
@@ -324,22 +396,31 @@
|
|
|
324
396
|
tabFeatures: "Features",
|
|
325
397
|
tabStyles: "Styles",
|
|
326
398
|
tabProxy: "Proxy",
|
|
399
|
+
tabBehavior: "Behavior",
|
|
327
400
|
tabAgents: "Global Prompt",
|
|
328
401
|
agentsDesc: "Written to ~/.zcode/AGENTS.md and used as default instructions in every session across all projects. Takes effect for new sessions; per-project AGENTS.md can extend or override it. Content over 100 KB is truncated by the app.",
|
|
329
402
|
agentsPlaceholder: "Instructions followed by all projects by default; save empty to remove the global prompt",
|
|
330
403
|
agentsSave: "Save",
|
|
331
404
|
agentsSaved: "Global prompt saved.",
|
|
332
405
|
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,
|
|
406
|
+
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
407
|
proxyPlaceholder: "http://127.0.0.1:7890",
|
|
335
408
|
proxySave: "Save",
|
|
336
409
|
proxySaved: "Proxy settings saved.",
|
|
337
410
|
proxyHint: "Save empty to clear the proxy.",
|
|
338
411
|
proxyTest: "Test",
|
|
339
412
|
proxyTesting: "Testing\u2026",
|
|
413
|
+
proxyTestEmpty: "Enter a proxy address first",
|
|
340
414
|
proxyTestFailed: "Test failed",
|
|
415
|
+
proxyScopePlugins: "Plugin marketplace",
|
|
416
|
+
proxyScopePluginsDesc: "Marketplace checks, installs and uninstalls (zcode CLI git operations) go through the proxy.",
|
|
417
|
+
proxyScopeDeps: "Plugin dependencies",
|
|
418
|
+
proxyScopeDepsDesc: "headroom and rtk installs, update checks and upgrades (pip and GitHub downloads) go through the proxy.",
|
|
419
|
+
proxyScopeSync: "Sync",
|
|
420
|
+
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
421
|
tabSync: "Sync",
|
|
342
|
-
|
|
422
|
+
tabDebug: "Debug",
|
|
423
|
+
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
424
|
syncUrlPlaceholder: "https://dav.example.com/dav/",
|
|
344
425
|
syncDir: "\u4E0A\u4F20\u76EE\u5F55",
|
|
345
426
|
syncDirPlaceholder: "zcode-pro",
|
|
@@ -347,7 +428,7 @@
|
|
|
347
428
|
syncPassword: "Password",
|
|
348
429
|
syncSave: "Save",
|
|
349
430
|
syncSaved: "Sync settings saved.",
|
|
350
|
-
syncFormHint: "Sync files go
|
|
431
|
+
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
432
|
syncRecLink: "Jianguoyun WebDAV",
|
|
352
433
|
syncRecSuffix: " \u2014 use the app password, not your account password.",
|
|
353
434
|
syncIncludeZcp: "ZCode Pro settings",
|
|
@@ -357,16 +438,44 @@
|
|
|
357
438
|
syncUpload: "Upload",
|
|
358
439
|
syncDownload: "Download",
|
|
359
440
|
syncUploading: "Uploading\u2026",
|
|
360
|
-
syncDownloading: "Downloading\u2026",
|
|
361
441
|
syncUploaded: "Uploaded to the server.",
|
|
362
442
|
syncDownloaded: "Restored from the server.",
|
|
363
443
|
syncLastPush: "Last upload",
|
|
364
444
|
syncLastPull: "Last download",
|
|
365
445
|
syncNever: "never",
|
|
366
446
|
syncConfirmTitle: "Download from the server",
|
|
367
|
-
syncConfirmDesc: "
|
|
368
|
-
syncConfirmGo: "
|
|
447
|
+
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?",
|
|
448
|
+
syncConfirmGo: "Import",
|
|
449
|
+
syncPickDesc: "Fixed names are always the latest version; timestamped files are the history each upload leaves behind. Import overwrites the matching local section.",
|
|
450
|
+
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
451
|
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.",
|
|
452
|
+
syncTest: "Test",
|
|
453
|
+
syncTesting: "Testing\u2026",
|
|
454
|
+
syncTestEmpty: "Enter the WebDAV URL first",
|
|
455
|
+
syncTestFailed: "Test failed",
|
|
456
|
+
syncTestStepConnect: "Connect",
|
|
457
|
+
syncTestStepDir: "Folder",
|
|
458
|
+
syncTestStepList: "Files",
|
|
459
|
+
syncTestFilesFound: "{n} backup file(s) on the server",
|
|
460
|
+
syncPickTitle: "Select a file",
|
|
461
|
+
syncPickLoading: "Loading files from the server\u2026",
|
|
462
|
+
syncPickEmpty: "No backups on the server yet. Upload from a computer first.",
|
|
463
|
+
syncVerImport: "Import",
|
|
464
|
+
syncVerImporting: "Importing\u2026",
|
|
465
|
+
syncVerDelete: "Delete",
|
|
466
|
+
syncVerSave: "Save to disk",
|
|
467
|
+
syncVerSaving: "Saving\u2026",
|
|
468
|
+
syncVerLatest: "Latest",
|
|
469
|
+
syncVerDeleteTitle: "Delete server file",
|
|
470
|
+
syncVerDeleteDesc: "This backup will be deleted from the server and cannot be recovered: ",
|
|
471
|
+
syncVerDeleted: "Backup deleted from the server.",
|
|
472
|
+
syncVerSaved: "Saved to",
|
|
473
|
+
devMode: "Developer mode",
|
|
474
|
+
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.',
|
|
475
|
+
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.',
|
|
476
|
+
devReload: "Reload ZCode Pro",
|
|
477
|
+
devReloading: "Reloading\u2026",
|
|
478
|
+
devReloadDesc: "Every ZCode window refreshes automatically within 2-3 seconds to load the new script.",
|
|
370
479
|
rowGapName: "Paragraph spacing",
|
|
371
480
|
rowGapDesc: "Vertical spacing between text blocks (turns, paragraphs inside answers).",
|
|
372
481
|
listSpacingName: "List spacing",
|
|
@@ -383,6 +492,8 @@
|
|
|
383
492
|
tableCellPaddingDesc: "Padding inside table cells; left input is vertical, right is horizontal.",
|
|
384
493
|
lineHeightName: "Answer line height",
|
|
385
494
|
lineHeightDesc: "Line height of answer text (multiplier).",
|
|
495
|
+
thinkingLineHeightName: "Work-log line height",
|
|
496
|
+
thinkingLineHeightDesc: "Line height of the \u201Cworked for\u2026\u201D history panel (tool entries and reasoning, multiplier).",
|
|
386
497
|
userLineHeightName: "Question line height",
|
|
387
498
|
userLineHeightDesc: "Line height of question text (multiplier).",
|
|
388
499
|
contentWidthName: "Content width",
|
|
@@ -397,6 +508,30 @@
|
|
|
397
508
|
featureSessionSwitchDesc: "alt+z toggles between the current and the last session; hold alt and press x/c to move the highlight across recently used sessions, release alt to switch (like alt+tab).",
|
|
398
509
|
featureTitleLock: "Keep renamed session titles",
|
|
399
510
|
featureTitleLockDesc: "Sessions you renamed keep their custom title: after new replies the app may show an auto-generated title instead, which reverts after a restart; this keeps the renamed title in the sidebar.",
|
|
511
|
+
tabTitleGen: "Task name prompt",
|
|
512
|
+
titleGenShortDesc: "When a new session starts answering, generates the task name with the chosen provider and prompt and saves it as a manual rename the built-in title never overrides.",
|
|
513
|
+
titleGenEnabled: "Enable",
|
|
514
|
+
titleGenProvider: "Provider",
|
|
515
|
+
titleGenProviderNone: "Custom endpoint (no provider)",
|
|
516
|
+
titleGenProviderSession: "Follow current session",
|
|
517
|
+
titleGenProviderDeleted: " (deleted)",
|
|
518
|
+
titleGenModel: "Model",
|
|
519
|
+
titleGenModelHint: "Pick from the list, or type a model id",
|
|
520
|
+
titleGenModelEmpty: "(not set)",
|
|
521
|
+
titleGenModelSessionHint: "Pick from the list; the first entry follows the session model",
|
|
522
|
+
titleGenModelFollowSession: "Follow the session model",
|
|
523
|
+
titleGenModelManualHint: "Type a model id",
|
|
524
|
+
titleGenBaseUrl: "Base URL",
|
|
525
|
+
titleGenApiKey: "API Key",
|
|
526
|
+
titleGenFormat: "Protocol",
|
|
527
|
+
titleGenPrompt: "Prompt",
|
|
528
|
+
titleGenPromptPlaceholder: "Leave empty for the built-in default prompt (button below shows it)",
|
|
529
|
+
titleGenPromptReset: "Use default prompt",
|
|
530
|
+
titleGenSample: "Test message",
|
|
531
|
+
titleGenTest: "Test",
|
|
532
|
+
titleGenTesting: "Generating\u2026",
|
|
533
|
+
titleGenTestOk: "Result: ",
|
|
534
|
+
titleGenTestFailed: "Generation failed",
|
|
400
535
|
featureWsRunning: "Running indicator on collapsed projects (experimental)",
|
|
401
536
|
featureWsRunningDesc: "Spins a collapsed project's icon while any of its sessions is still running; stops when they all finish or the project is expanded. While spinning, the project is briefly re-expanded in the background every 60 s to re-check and then collapsed \u2014 rows stay hidden, with only a subtle quarter-second height ripple at the project.",
|
|
402
537
|
tabPerformance: "Performance",
|
|
@@ -446,7 +581,7 @@
|
|
|
446
581
|
featurePinnedExpand: "Keep projects collapsed for pinned sessions (experimental)",
|
|
447
582
|
featurePinnedExpandDesc: "Keeps the project collapsed after clicking a pinned session. Note: it briefly expands first, then collapses.",
|
|
448
583
|
featureAutoUpdatePlugins: "Auto-update zcode-plugins plugins",
|
|
449
|
-
featureAutoUpdatePluginsDesc: "Checks and updates installed zcode-plugins plugins on startup (
|
|
584
|
+
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
585
|
pluginsUpdateTitle: "Plugin updates \xB7 zcode-plugins",
|
|
451
586
|
pluginsCheckNow: "Check & update",
|
|
452
587
|
pluginsUpdating: "Updating plugins\u2026",
|
|
@@ -458,7 +593,7 @@
|
|
|
458
593
|
pluginsAutoUpdated: "zcode-plugins updated",
|
|
459
594
|
tabVision: "Vision",
|
|
460
595
|
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
|
|
596
|
+
visionEnabled: "Enable",
|
|
462
597
|
visionForceIntercept: "Intercept even if the main model sees images",
|
|
463
598
|
visionMode: "Chain mode",
|
|
464
599
|
visionModeFallback: "Fallback",
|
|
@@ -471,10 +606,6 @@
|
|
|
471
606
|
visionMoveDown: "Down",
|
|
472
607
|
visionName: "Name",
|
|
473
608
|
visionUseProvider: "Provider",
|
|
474
|
-
visionUseProviderHint: "Pick from the list or type: session = follow the current session provider, or a provider name/ID; baseUrl/API key/format follow that provider",
|
|
475
|
-
visionUseProviderNone: "Not following (enter base URL)",
|
|
476
|
-
visionUseProviderSession: "Follow session provider (session)",
|
|
477
|
-
visionUseProviderUnknown: "Unknown provider; recognition will fail. Pick from the list or type session",
|
|
478
609
|
visionSkipAfterFailures: "Skip after failures",
|
|
479
610
|
visionSkipAfterFailuresHint: "After this many consecutive failures a proxy is skipped and the next one is tried; 0 = never skip",
|
|
480
611
|
visionSkipMinutes: "Skip minutes",
|
|
@@ -483,21 +614,21 @@
|
|
|
483
614
|
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
615
|
visionBaseUrl: "Base URL",
|
|
485
616
|
visionModel: "Model",
|
|
486
|
-
visionFormat: "Format",
|
|
487
617
|
visionApiKey: "API Key",
|
|
488
618
|
visionApiKeyHint: "Leave empty to reuse the GLM subscription key",
|
|
489
619
|
visionPrompt: "Recognition prompt ({prev} = previous step in pipeline)",
|
|
490
620
|
visionTest: "Test",
|
|
491
621
|
visionTesting: "Testing\u2026",
|
|
492
622
|
visionTestFailed: "Vision proxy test failed",
|
|
493
|
-
visionTestOutput: "Test output",
|
|
494
623
|
visionCompressKB: "Compress threshold KB",
|
|
495
624
|
visionCompressKBHint: "Images above this size are compressed first (max edge 2000, JPEG); 0 = never",
|
|
496
625
|
visionLoadFailed: "Failed to load the vision config",
|
|
497
626
|
tabRtk: "rtk",
|
|
498
627
|
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
|
|
628
|
+
rtkEnabled: "Enable",
|
|
500
629
|
rtkNotInstalled: "rtk is not installed. The settings below take effect after installation (/rtk-setup in a session).",
|
|
630
|
+
rtkInstallBin: "Install rtk binary",
|
|
631
|
+
rtkBinInstalled: "rtk installed; PATH takes effect for sessions after signing out and back in \u2014 the plugin hook works immediately",
|
|
501
632
|
rtkWhitelistTitle: "Whitelist (pass through without compression)",
|
|
502
633
|
rtkBuiltinLabel: "Built-in exemptions (read-only, follow plugin updates):",
|
|
503
634
|
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 +641,25 @@
|
|
|
510
641
|
tabHeadroom: "Headroom",
|
|
511
642
|
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
643
|
headroomBinMissing: "The headroom program was not found, so the proxy cannot start. The settings below take effect once it is installed.",
|
|
644
|
+
hrInstallBin: "Install headroom binary",
|
|
645
|
+
hrBinInstalled: "headroom installed; reopen a session and the hook will start the proxy automatically",
|
|
513
646
|
headroomInstallTitle: "headroom plugin not installed",
|
|
514
647
|
headroomInstallDesc: "Install it from the zcode-plugins marketplace to manage the compression proxy here; restarting the session afterwards is recommended.",
|
|
515
648
|
headroomInstall: "Install",
|
|
516
649
|
headroomInstalling: "Installing\u2026",
|
|
517
650
|
headroomInstalled: "headroom plugin installed",
|
|
518
651
|
headroomInstallRetry: "Installation did not take effect; retry or install it from the marketplace manually",
|
|
652
|
+
pluginInstallCardTitle: "{name} plugin not installed",
|
|
653
|
+
pluginInstallCardDesc: "Install it from the zcode-plugins marketplace to manage it here; restarting the session afterwards is recommended.",
|
|
654
|
+
pluginInstallDone: "{name} plugin installed",
|
|
655
|
+
pluginEnable: "Enable",
|
|
656
|
+
hrStarting: "Starting compression proxy\u2026",
|
|
657
|
+
hrStarted: "Compression proxy started",
|
|
658
|
+
hrStartTimeout: "Proxy start timed out (90s); check ~/.zcode-headroom-proxy.log",
|
|
659
|
+
hrStopping: "Stopping compression proxy\u2026",
|
|
660
|
+
hrRestarting: "Restarting compression proxy\u2026",
|
|
661
|
+
hrStopped: "Compression proxy stopped",
|
|
662
|
+
hrUsageNone: "No providers route through headroom; nothing changed",
|
|
519
663
|
headroomLoadFailed: "Failed to load the Headroom config",
|
|
520
664
|
headroomStatusTitle: "Status",
|
|
521
665
|
headroomStatusLoadFailed: "Failed to load the status",
|
|
@@ -541,7 +685,7 @@
|
|
|
541
685
|
headroomRestart: "Restart",
|
|
542
686
|
headroomStopAction: "Stop",
|
|
543
687
|
headroomStopTitle: "Stop the Headroom proxy",
|
|
544
|
-
headroomStopDesc: "
|
|
688
|
+
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
689
|
headroomStoppedWarn: "Proxy stopped; providers pointing at 127.0.0.1 cannot connect.",
|
|
546
690
|
headroomBackend: "Compression device",
|
|
547
691
|
headroomBackendAuto: "Auto \xB7 GPU first",
|
|
@@ -559,8 +703,6 @@
|
|
|
559
703
|
headroomInterval: "Watch interval",
|
|
560
704
|
headroomIntervalDesc: "Seconds between power checks (10\u20133600, default 60); applies from the next round, no restart needed.",
|
|
561
705
|
headroomSecUnit: "s",
|
|
562
|
-
headroomVersionPlugin: "plugin",
|
|
563
|
-
headroomVersionBin: "program",
|
|
564
706
|
upgradeCheck: "Check update",
|
|
565
707
|
upgradeChecking: "Checking\u2026",
|
|
566
708
|
upgradeUpToDate: "Up to date ({v})",
|
|
@@ -572,7 +714,6 @@
|
|
|
572
714
|
upgradeDone: "Updated to {v}",
|
|
573
715
|
upgradeFinished: "Update finished",
|
|
574
716
|
upgradeCheckFailed: "Update check failed",
|
|
575
|
-
version: "Version",
|
|
576
717
|
close: "Close",
|
|
577
718
|
cancel: "Cancel",
|
|
578
719
|
pathLabel: "Path",
|
|
@@ -678,7 +819,9 @@
|
|
|
678
819
|
"sync-remote-missing": "No synced data on the server yet; upload from another computer first",
|
|
679
820
|
"sync-remote-invalid": "The URL already holds a different file; use another file path",
|
|
680
821
|
"sync-request": "The WebDAV request failed",
|
|
681
|
-
"sync-run": "Sync failed"
|
|
822
|
+
"sync-run": "Sync failed",
|
|
823
|
+
"sync-file-invalid": "Invalid backup file name",
|
|
824
|
+
"sync-export": "Failed to save the backup to disk"
|
|
682
825
|
};
|
|
683
826
|
function errText(res) {
|
|
684
827
|
if (!res) return "";
|
|
@@ -753,8 +896,9 @@
|
|
|
753
896
|
"div",
|
|
754
897
|
{
|
|
755
898
|
id: "__zcodepro_toast__",
|
|
756
|
-
class: "fixed bottom-6
|
|
757
|
-
|
|
899
|
+
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"),
|
|
900
|
+
// left 用内联样式:ZCode 的 Tailwind 未编译 left-6/right-6 工具类(bottom-6 有)
|
|
901
|
+
style: "animation:zcodepro-fade-in .18s ease; left: 1.5rem;"
|
|
758
902
|
},
|
|
759
903
|
h("span", { class: "truncate" }, text)
|
|
760
904
|
);
|
|
@@ -766,7 +910,7 @@
|
|
|
766
910
|
var overlayClassBare = "fixed inset-0 isolate z-50 flex items-center justify-center duration-100 p-4 platform-linux-desktop:top-12";
|
|
767
911
|
var contentClass = "w-full sm:max-w-md rounded-2xl border-none bg-popover/98 p-5 text-ui-base/relaxed text-foreground ring-border shadow-2xl";
|
|
768
912
|
var dialogStack = [];
|
|
769
|
-
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true }) {
|
|
913
|
+
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true, bodyClass = "" }) {
|
|
770
914
|
const L = t();
|
|
771
915
|
const prevActive = document.activeElement;
|
|
772
916
|
let cleanupDrag = null;
|
|
@@ -810,7 +954,7 @@
|
|
|
810
954
|
titleEl,
|
|
811
955
|
...description ? [h("p", { class: "mt-2 text-ui-sm/relaxed text-foreground-subtle" }, description)] : []
|
|
812
956
|
);
|
|
813
|
-
const body = h("div", { class: "
|
|
957
|
+
const body = h("div", { class: "zcodepro-dialog-body " + (bodyClass || "mt-4") });
|
|
814
958
|
content.append(body);
|
|
815
959
|
let restorePos = null;
|
|
816
960
|
if (draggable) {
|
|
@@ -1072,7 +1216,7 @@
|
|
|
1072
1216
|
"data-state": checked ? "on" : "off"
|
|
1073
1217
|
}, knob);
|
|
1074
1218
|
const extraEl = extra ? h("div", {
|
|
1075
|
-
class: "flex shrink-0 items-center
|
|
1219
|
+
class: "flex shrink-0 items-center",
|
|
1076
1220
|
onClick: (e) => {
|
|
1077
1221
|
e.stopPropagation();
|
|
1078
1222
|
},
|
|
@@ -1086,7 +1230,7 @@
|
|
|
1086
1230
|
const row = h(
|
|
1087
1231
|
"div",
|
|
1088
1232
|
{
|
|
1089
|
-
class: `flex cursor-pointer items-
|
|
1233
|
+
class: `flex cursor-pointer items-center gap-2 rounded-lg ${desc ? "p-2" : "p-1.5"} transition-colors hover:bg-surface-hover`,
|
|
1090
1234
|
onClick: () => {
|
|
1091
1235
|
onToggle();
|
|
1092
1236
|
}
|
|
@@ -1174,13 +1318,14 @@
|
|
|
1174
1318
|
align-items: center;
|
|
1175
1319
|
justify-content: center;
|
|
1176
1320
|
height: 24px;
|
|
1177
|
-
padding: 0
|
|
1321
|
+
padding: 0 8px;
|
|
1178
1322
|
border: none;
|
|
1179
1323
|
border-radius: 9999px;
|
|
1180
1324
|
background: transparent;
|
|
1181
1325
|
cursor: pointer;
|
|
1182
1326
|
font-size: 12px;
|
|
1183
1327
|
line-height: 1;
|
|
1328
|
+
white-space: nowrap;
|
|
1184
1329
|
color: var(--color-muted-foreground, #888);
|
|
1185
1330
|
transition: color 0.15s ease, background-color 0.15s ease;
|
|
1186
1331
|
}
|
|
@@ -1269,6 +1414,8 @@
|
|
|
1269
1414
|
.zcodepro-textarea:disabled { opacity: 0.5; }
|
|
1270
1415
|
/* \u5C0F\u578B\u6587\u672C\u57DF\uFF08\u89C6\u89C9\u4EE3\u7406\u63D0\u793A\u8BCD\u7B49\uFF09\uFF1A11rem \u6700\u5C0F\u9AD8\u5EA6\u53EA\u5C5E\u4E8E\u5168\u5C40\u63D0\u793A\u8BCD\u5927\u7F16\u8F91\u6846\uFF0C\u8FD9\u91CC\u6309 rows \u5B9A\u9AD8 */
|
|
1271
1416
|
.zcodepro-textarea.zcodepro-textarea-sm { min-height: 0; }
|
|
1417
|
+
/* \u5168\u5C40\u63D0\u793A\u8BCD\u5927\u7F16\u8F91\u6846\uFF1A\u9ED8\u8BA4/\u6700\u5927\u9AD8\u5EA6\u90FD\u6BD4\u9ED8\u8BA4\u6587\u672C\u57DF\u66F4\u9AD8 */
|
|
1418
|
+
.zcodepro-textarea.zcodepro-textarea-lg { min-height: 16rem; max-height: 40rem; }
|
|
1272
1419
|
/* \u884C\u9AD8\u6ED1\u6746\uFF08\u6837\u5F0F\u8C03\u6574\u6807\u7B7E\u9875\uFF09 */
|
|
1273
1420
|
.zcodepro-range {
|
|
1274
1421
|
-webkit-appearance: none;
|
|
@@ -1454,6 +1601,14 @@
|
|
|
1454
1601
|
}
|
|
1455
1602
|
/* \u539F\u4FA7\u680F\u83DC\u5355\u6574\u4F53\u9690\u85CF\uFF08toolbar-icons \u5F00\u542F\u65F6\uFF09 */
|
|
1456
1603
|
.zcodepro-tb-hidden { display: none !important; }
|
|
1604
|
+
/* \u539F\u751F\u9876\u680F\u65B0\u5EFA\u4EFB\u52A1\u6309\u94AE\uFF08\u6587\u4EF6\u67E5\u770B\u7B49\u5B50\u9875\u5C55\u5F00\u7684\u90A3\u4E2A\uFF09\uFF1A\u5E38\u9A7B DOM\u3001\u9760\u52A8\u753B\u5BB9\u5668
|
|
1605
|
+
\u5728 w-7/w-0 \u95F4\u5207\u6362\u663E\u9690\u3002\u529F\u80FD\u5F00\u542F\u671F\u95F4\u6574\u4F53\u9489\u6B7B\u6536\u8D77\u6001\u2014\u2014\u65B0\u5EFA\u5165\u53E3\u7EDF\u4E00\u7531\u6211\u4EEC
|
|
1606
|
+
\u7684\u6309\u94AE\u884C\u63D0\u4F9B\uFF0C\u4E5F\u5C31\u4E0D\u518D\u9700\u8981\u968F\u5B50\u9875\u8FDB\u51FA\u52A8\u6001\u663E\u9690\u81EA\u5DF1\u7684\u65B0\u5EFA\u6309\u94AE */
|
|
1607
|
+
.zcodepro-tb-hidden-native div[class*="transition-[opacity,width]"] {
|
|
1608
|
+
width: 0 !important;
|
|
1609
|
+
opacity: 0 !important;
|
|
1610
|
+
pointer-events: none !important;
|
|
1611
|
+
}
|
|
1457
1612
|
/* \u5DF2\u7F6E\u9876\u5206\u533A\u53EF\u6298\u53E0\uFF08pinned-collapse.js\uFF09\uFF1A\u6807\u9898\u6574\u884C\u53EF\u70B9\uFF0C\u6298\u53E0\u65F6\u85CF\u8D77\u4EFB\u52A1\u5217\u8868\uFF0C
|
|
1458
1613
|
chevron \u65CB\u5411\u4E0E\u201C\u9879\u76EE\u201D\u5206\u533A\u4E00\u81F4\uFF08\u6536\u8D77\u6307\u5411\u53F3\u4FA7\uFF09 */
|
|
1459
1614
|
.zcodepro-pin-head {
|
|
@@ -2108,6 +2263,12 @@
|
|
|
2108
2263
|
const path = resolveTargetPath(content);
|
|
2109
2264
|
if (!path) return;
|
|
2110
2265
|
const L = t();
|
|
2266
|
+
const fire = (endpoint, label) => {
|
|
2267
|
+
rpc(endpoint, { method: "POST", body: { path } }).then((r) => {
|
|
2268
|
+
if (r && r.ok === false) showToast(`${label}\u5931\u8D25\uFF1A${r.error || "\u672A\u77E5\u9519\u8BEF"}`, "error");
|
|
2269
|
+
}).catch(() => {
|
|
2270
|
+
});
|
|
2271
|
+
};
|
|
2111
2272
|
const noApps = items.find((el) => NO_APPS_TEXTS.some((x) => itemText(el) === x)) || content.querySelector('[data-disabled][role="menuitem"]');
|
|
2112
2273
|
const openAnchor = noApps && content.contains(noApps) ? noApps : copyAbs;
|
|
2113
2274
|
appendMenuItem(content, copyAbs, openAnchor, {
|
|
@@ -2115,10 +2276,7 @@
|
|
|
2115
2276
|
label: L.fileOpenDefault,
|
|
2116
2277
|
icon: ICON_OPEN_DEFAULT,
|
|
2117
2278
|
onPick: () => {
|
|
2118
|
-
|
|
2119
|
-
void rpc("/open-path", { method: "POST", body: { path } });
|
|
2120
|
-
} catch {
|
|
2121
|
-
}
|
|
2279
|
+
void fire("/open-path", L.fileOpenDefault);
|
|
2122
2280
|
}
|
|
2123
2281
|
});
|
|
2124
2282
|
appendMenuItem(content, copyAbs, copyAbs, {
|
|
@@ -2126,10 +2284,7 @@
|
|
|
2126
2284
|
label: L.fileReveal,
|
|
2127
2285
|
icon: ICON_REVEAL,
|
|
2128
2286
|
onPick: () => {
|
|
2129
|
-
|
|
2130
|
-
void rpc("/reveal-path", { method: "POST", body: { path } });
|
|
2131
|
-
} catch {
|
|
2132
|
-
}
|
|
2287
|
+
void fire("/reveal-path", L.fileReveal);
|
|
2133
2288
|
}
|
|
2134
2289
|
});
|
|
2135
2290
|
})();
|
|
@@ -2341,6 +2496,56 @@
|
|
|
2341
2496
|
}, true);
|
|
2342
2497
|
}
|
|
2343
2498
|
|
|
2499
|
+
// src/inject/provider-fields.js
|
|
2500
|
+
var PROVIDER_FIELD_CLS = "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";
|
|
2501
|
+
function comboField(current2, options, onChange, { disabled = false, placeholder = "", staleLabel = "\uFF08\u624B\u52A8\u8F93\u5165\uFF09", emptyLabel = "" } = {}) {
|
|
2502
|
+
const sel = h("select", { class: PROVIDER_FIELD_CLS, disabled: disabled || void 0 });
|
|
2503
|
+
const input = h("input", { type: "text", value: current2, placeholder, class: PROVIDER_FIELD_CLS, disabled: disabled || void 0 });
|
|
2504
|
+
const sync3 = () => {
|
|
2505
|
+
const cur = input.value;
|
|
2506
|
+
const opts = [...options];
|
|
2507
|
+
if (cur && !opts.some((o) => o.value === cur)) opts.push({ value: cur, label: `${cur}${staleLabel}` });
|
|
2508
|
+
if (!cur && !opts.some((o) => o.value === "")) opts.unshift({ value: "", label: emptyLabel });
|
|
2509
|
+
sel.replaceChildren(...opts.map((o) => h("option", { value: o.value, title: o.value }, o.label)));
|
|
2510
|
+
sel.value = cur;
|
|
2511
|
+
};
|
|
2512
|
+
sel.addEventListener("change", () => {
|
|
2513
|
+
input.value = sel.value;
|
|
2514
|
+
onChange(sel.value, "select");
|
|
2515
|
+
});
|
|
2516
|
+
input.addEventListener("input", () => onChange(input.value, "type"));
|
|
2517
|
+
input.addEventListener("blur", () => sync3());
|
|
2518
|
+
sync3();
|
|
2519
|
+
return h("div", { class: "flex flex-col gap-1" }, sel, input);
|
|
2520
|
+
}
|
|
2521
|
+
function providerOptionsOf(providers, L) {
|
|
2522
|
+
return [
|
|
2523
|
+
{ value: "", label: L.titleGenProviderNone },
|
|
2524
|
+
{ value: "session", label: L.titleGenProviderSession },
|
|
2525
|
+
...providers.map((p) => ({ value: p.id, label: p.name }))
|
|
2526
|
+
];
|
|
2527
|
+
}
|
|
2528
|
+
function modelOptionsOf(providerValue, providers, { followSession = false, followSessionLabel = "" } = {}) {
|
|
2529
|
+
const v = (providerValue || "").trim();
|
|
2530
|
+
const cur = providers.find((p) => p.id === v);
|
|
2531
|
+
if (cur) return cur.models.map((m) => ({ value: m, label: m }));
|
|
2532
|
+
if (v === "session") {
|
|
2533
|
+
const head = followSession && followSessionLabel ? [{ value: "", label: followSessionLabel }] : [];
|
|
2534
|
+
return [...head, ...[...new Set(providers.flatMap((p) => p.models))].map((m) => ({ value: m, label: m }))];
|
|
2535
|
+
}
|
|
2536
|
+
return [];
|
|
2537
|
+
}
|
|
2538
|
+
function modelPlaceholderOf(providerValue, L) {
|
|
2539
|
+
const v = (providerValue || "").trim();
|
|
2540
|
+
if (v === "session") return L.titleGenModelSessionHint;
|
|
2541
|
+
if (v === "") return L.titleGenModelManualHint;
|
|
2542
|
+
return L.titleGenModelHint;
|
|
2543
|
+
}
|
|
2544
|
+
function isManualConn(providerValue, providers) {
|
|
2545
|
+
const v = (providerValue || "").trim();
|
|
2546
|
+
return v === "" || v !== "session" && !providers.some((p) => p.id === v);
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2344
2549
|
// src/inject/features/styles.js
|
|
2345
2550
|
var STYLE_DEFAULTS = {
|
|
2346
2551
|
rowGap: 20,
|
|
@@ -2361,6 +2566,8 @@
|
|
|
2361
2566
|
// 单元格左右边距(应用默认 3px)
|
|
2362
2567
|
lineHeight: 1.75,
|
|
2363
2568
|
// 回答行高(leading-[1.75],挂在答案内容容器上)
|
|
2569
|
+
thinkingLineHeight: 1.5,
|
|
2570
|
+
// 思考行高:“已工作/工作中”过程视图的行距(实测应用默认 1.5;范围见 buildCss 注释)
|
|
2364
2571
|
userLineHeight: 1.5,
|
|
2365
2572
|
// 提问行高(用户消息文本容器,默认 normal=1.5)
|
|
2366
2573
|
contentWidth: null,
|
|
@@ -2457,6 +2664,12 @@
|
|
|
2457
2664
|
if (typeof lh === "number" && Number.isFinite(lh) && lh >= 0.8) {
|
|
2458
2665
|
parts.push(`${CONV} .space-y-4{line-height:${lh} !important;}`);
|
|
2459
2666
|
}
|
|
2667
|
+
const tlh = styles.thinkingLineHeight;
|
|
2668
|
+
if (typeof tlh === "number" && Number.isFinite(tlh) && tlh >= 0.8) {
|
|
2669
|
+
parts.push(
|
|
2670
|
+
`[data-testid^="chat-assistant-history-content"]{line-height:${tlh} !important;}`
|
|
2671
|
+
);
|
|
2672
|
+
}
|
|
2460
2673
|
const ulh = styles.userLineHeight;
|
|
2461
2674
|
if (typeof ulh === "number" && Number.isFinite(ulh) && ulh >= 0.8) {
|
|
2462
2675
|
parts.push(`${CONV} [class*="user-row"] .whitespace-pre-wrap{line-height:${ulh} !important;}`);
|
|
@@ -2553,7 +2766,10 @@
|
|
|
2553
2766
|
tableCellPaddingV: `${CONV} td, ${CONV} th`,
|
|
2554
2767
|
tableCellPaddingH: `${CONV} td, ${CONV} th`,
|
|
2555
2768
|
codeLineHeight: `${CONV} diffs-container, ${CONV} pre`,
|
|
2556
|
-
lineHeight: `${CONV} .space-y-4`,
|
|
2769
|
+
lineHeight: `${CONV} .space-y-4:not([data-reasoning-content] *)`,
|
|
2770
|
+
// 思考行高作用在“已工作/工作中”过程视图容器上;视图折叠未挂载时不标
|
|
2771
|
+
// (触发行不属此设置范围,不额外描边)
|
|
2772
|
+
thinkingLineHeight: `[data-testid^="chat-assistant-history-content"]`,
|
|
2557
2773
|
userLineHeight: `${CONV} [class*="user-row"] .whitespace-pre-wrap`,
|
|
2558
2774
|
contentWidth: "[data-v4-timeline-content-column]",
|
|
2559
2775
|
sidebarProjectSpacing: '[data-testid^="workspace-item-"]',
|
|
@@ -2600,11 +2816,13 @@
|
|
|
2600
2816
|
} catch {
|
|
2601
2817
|
}
|
|
2602
2818
|
}
|
|
2603
|
-
function makeUpgradeControls({ endpoint, metaRefresh }) {
|
|
2819
|
+
function makeUpgradeControls({ endpoint, metaRefresh, idleText }) {
|
|
2604
2820
|
const L = t();
|
|
2605
2821
|
const state = h("span", { class: "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed text-foreground-subtle" });
|
|
2822
|
+
const hasIdle = () => typeof idleText === "function";
|
|
2606
2823
|
const setState = (text, kind = "") => {
|
|
2607
|
-
|
|
2824
|
+
const shown = text || (hasIdle() ? idleText() || "" : "");
|
|
2825
|
+
state.textContent = shown ? kind === "error" ? shown : ` \xB7 ${shown}` : "";
|
|
2608
2826
|
state.className = "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed " + (kind === "error" ? "text-destructive" : "text-foreground-subtle");
|
|
2609
2827
|
};
|
|
2610
2828
|
let latest = null;
|
|
@@ -2722,6 +2940,7 @@
|
|
|
2722
2940
|
const res = await rpc(endpoint + "/upgrade");
|
|
2723
2941
|
if (res.ok && res.upgrade && res.upgrade.running) pollStart();
|
|
2724
2942
|
})();
|
|
2943
|
+
setState("");
|
|
2725
2944
|
return { btn, state, stop: stopPoll };
|
|
2726
2945
|
}
|
|
2727
2946
|
function openSettingsDialog() {
|
|
@@ -2732,8 +2951,10 @@
|
|
|
2732
2951
|
openDialog({
|
|
2733
2952
|
title: L.settingsTitle,
|
|
2734
2953
|
// 宽度类必须用宿主样式表已有的工具类(注入的类名不会生成 CSS):
|
|
2735
|
-
// sm:max-w-3xl 不存在会失去约束拉满全屏;max-w-
|
|
2736
|
-
|
|
2954
|
+
// sm:max-w-3xl 不存在会失去约束拉满全屏;max-w-3xl=48rem 存在——英文界面
|
|
2955
|
+
// 标签栏较长,42rem 会挤出一块空白并触发横向滚动
|
|
2956
|
+
width: "max-w-3xl",
|
|
2957
|
+
bodyClass: "mt-1",
|
|
2737
2958
|
overlay: "none",
|
|
2738
2959
|
draggable: true,
|
|
2739
2960
|
posKey: "settings",
|
|
@@ -2794,7 +3015,9 @@
|
|
|
2794
3015
|
const config = await getConfig(true);
|
|
2795
3016
|
const agentsRes = await rpc("/agents");
|
|
2796
3017
|
const visionRes = await rpc("/vision");
|
|
2797
|
-
const
|
|
3018
|
+
const titleGenRes = await rpc("/title-gen");
|
|
3019
|
+
const titleGenProvidersRes = await rpc("/title-gen/providers");
|
|
3020
|
+
const titleGenProviders = titleGenProvidersRes.ok && Array.isArray(titleGenProvidersRes.providers) ? titleGenProvidersRes.providers : [];
|
|
2798
3021
|
const rtkRes = await rpc("/rtk");
|
|
2799
3022
|
const headroomRes = await rpc("/headroom");
|
|
2800
3023
|
const setFeature = async (key, value) => {
|
|
@@ -2816,7 +3039,7 @@
|
|
|
2816
3039
|
"data-zcodepro-status": "1"
|
|
2817
3040
|
},
|
|
2818
3041
|
h("span", { class: "inline-block size-2 rounded-full bg-emerald-500" }),
|
|
2819
|
-
h("span", { class: "text-foreground-subtle/70" }, `${
|
|
3042
|
+
h("span", { class: "text-foreground-subtle/70" }, `${health.version} \xB7 ${HELPER_URL}`)
|
|
2820
3043
|
);
|
|
2821
3044
|
const rows = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
2822
3045
|
const refreshRows = () => {
|
|
@@ -2930,7 +3153,7 @@
|
|
|
2930
3153
|
const runPluginsUpdate = async () => {
|
|
2931
3154
|
pluginsBtn.disabled = true;
|
|
2932
3155
|
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
2933
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {
|
|
3156
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
2934
3157
|
pluginsBtn.disabled = false;
|
|
2935
3158
|
if (!res.ok) {
|
|
2936
3159
|
pluginsStatusLine.textContent = "";
|
|
@@ -2985,25 +3208,30 @@
|
|
|
2985
3208
|
);
|
|
2986
3209
|
const paneStyles = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2987
3210
|
const panePerf = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2988
|
-
const paneAgents = h("div", { role: "tabpanel", class: "mt-
|
|
3211
|
+
const paneAgents = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
2989
3212
|
const paneProxy = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2990
3213
|
const paneSync = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2991
3214
|
const paneVision = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2992
3215
|
const paneRtk = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2993
3216
|
const paneHeadroom = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
2994
|
-
const
|
|
3217
|
+
const paneTitleGen = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
3218
|
+
const paneDebug = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
3219
|
+
const panes = { features: paneFeatures, styles: paneStyles, perf: panePerf, agents: paneAgents, proxy: paneProxy, sync: paneSync, vision: paneVision, headroom: paneHeadroom, rtk: paneRtk, debug: paneDebug };
|
|
2995
3220
|
const tabDefs = [
|
|
2996
3221
|
["features", L.tabFeatures],
|
|
3222
|
+
["agents", L.tabBehavior],
|
|
2997
3223
|
["styles", L.tabStyles],
|
|
2998
3224
|
["perf", L.tabPerformance],
|
|
2999
|
-
["agents", L.tabAgents],
|
|
3000
3225
|
["proxy", L.tabProxy],
|
|
3001
3226
|
["sync", L.tabSync],
|
|
3002
3227
|
["vision", L.tabVision],
|
|
3003
3228
|
["headroom", L.tabHeadroom],
|
|
3004
|
-
["rtk", L.tabRtk]
|
|
3229
|
+
["rtk", L.tabRtk],
|
|
3230
|
+
// “调试”标签页只对开发模式生效的用户显示(配置开关或 ZCODEPRO_DEV=1),
|
|
3231
|
+
// 普通用户不可见
|
|
3232
|
+
...config.devMode === true || config.devActive === true ? [["debug", L.tabDebug]] : []
|
|
3005
3233
|
];
|
|
3006
|
-
const tablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist mt-
|
|
3234
|
+
const tablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist mt-1" });
|
|
3007
3235
|
const renderTabs = () => tablist.replaceChildren(...tabDefs.map(([id, label]) => h("button", {
|
|
3008
3236
|
type: "button",
|
|
3009
3237
|
role: "tab",
|
|
@@ -3119,6 +3347,7 @@
|
|
|
3119
3347
|
styleCell(L.rowGapName, L.rowGapDesc, "rowGap"),
|
|
3120
3348
|
styleCell(L.userLineHeightName, L.userLineHeightDesc, "userLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3121
3349
|
styleCell(L.lineHeightName, L.lineHeightDesc, "lineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3350
|
+
styleCell(L.thinkingLineHeightName, L.thinkingLineHeightDesc, "thinkingLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3122
3351
|
styleCell(L.codeLineHeightName, L.codeLineHeightDesc, "codeLineHeight", { min: 1, max: 3, step: 0.05, unit: "x" }),
|
|
3123
3352
|
styleCell(L.listSpacingName, L.listSpacingDesc, "listSpacing"),
|
|
3124
3353
|
styleCell(L.listItemSpacingName, L.listItemSpacingDesc, "listItemSpacing"),
|
|
@@ -3211,7 +3440,7 @@
|
|
|
3211
3440
|
)
|
|
3212
3441
|
);
|
|
3213
3442
|
const agentsArea = h("textarea", {
|
|
3214
|
-
class: "zcodepro-textarea",
|
|
3443
|
+
class: "zcodepro-textarea zcodepro-textarea-lg",
|
|
3215
3444
|
placeholder: L.agentsPlaceholder,
|
|
3216
3445
|
spellcheck: "false"
|
|
3217
3446
|
});
|
|
@@ -3242,12 +3471,36 @@
|
|
|
3242
3471
|
agentsSaveBtn.disabled = false;
|
|
3243
3472
|
}
|
|
3244
3473
|
};
|
|
3245
|
-
|
|
3474
|
+
const agentsPromptPane = h("div", { class: "mt-4" });
|
|
3475
|
+
agentsPromptPane.append(
|
|
3246
3476
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.agentsDesc),
|
|
3247
3477
|
...agentsFailed ? [h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.agentsLoadFailed + ": " + errText(agentsRes))] : [],
|
|
3248
3478
|
h("div", { class: "mt-3" }, agentsArea),
|
|
3249
3479
|
h("div", { class: "mt-3 flex justify-end" }, agentsSaveBtn)
|
|
3250
3480
|
);
|
|
3481
|
+
let agentsSubTab = "prompt";
|
|
3482
|
+
const agentsSubPanes = { prompt: agentsPromptPane, titleGen: paneTitleGen };
|
|
3483
|
+
const agentsSubList = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist" });
|
|
3484
|
+
const renderAgentsSubTabs = () => {
|
|
3485
|
+
agentsSubList.replaceChildren(...[
|
|
3486
|
+
["prompt", L.tabAgents],
|
|
3487
|
+
["titleGen", L.tabTitleGen]
|
|
3488
|
+
].map(([id, label]) => h("button", {
|
|
3489
|
+
type: "button",
|
|
3490
|
+
role: "tab",
|
|
3491
|
+
class: "zcodepro-tab",
|
|
3492
|
+
"aria-selected": String(agentsSubTab === id),
|
|
3493
|
+
"data-state": agentsSubTab === id ? "active" : "inactive",
|
|
3494
|
+
onClick: () => {
|
|
3495
|
+
agentsSubTab = id;
|
|
3496
|
+
for (const [pid, pane] of Object.entries(agentsSubPanes)) pane.style.display = pid === id ? "" : "none";
|
|
3497
|
+
renderAgentsSubTabs();
|
|
3498
|
+
}
|
|
3499
|
+
}, label)));
|
|
3500
|
+
};
|
|
3501
|
+
for (const [pid, pane] of Object.entries(agentsSubPanes)) pane.style.display = pid === agentsSubTab ? "" : "none";
|
|
3502
|
+
renderAgentsSubTabs();
|
|
3503
|
+
paneAgents.append(agentsSubList, agentsPromptPane, paneTitleGen);
|
|
3251
3504
|
const savedProxy = typeof config.proxy === "string" ? config.proxy : "";
|
|
3252
3505
|
const proxyInputCls = "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";
|
|
3253
3506
|
const proxyInput = h("input", { type: "text", value: savedProxy, placeholder: L.proxyPlaceholder, spellcheck: "false", class: proxyInputCls + " min-w-0 flex-1" });
|
|
@@ -3278,6 +3531,11 @@
|
|
|
3278
3531
|
}, "shrink-0");
|
|
3279
3532
|
const runProxyTest = async () => {
|
|
3280
3533
|
if (proxyTesting) return;
|
|
3534
|
+
if (!proxyInput.value.trim()) {
|
|
3535
|
+
proxyTestState.className = "mt-2 text-ui-xs/relaxed text-amber-500";
|
|
3536
|
+
proxyTestState.textContent = L.proxyTestEmpty;
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
3281
3539
|
proxyTesting = true;
|
|
3282
3540
|
proxyTestBtn.disabled = true;
|
|
3283
3541
|
proxyTestBtn.textContent = L.proxyTesting;
|
|
@@ -3297,6 +3555,37 @@
|
|
|
3297
3555
|
proxyTestState.className = "mt-2 text-ui-xs/relaxed " + (allOk ? "text-foreground-subtle" : "text-amber-500");
|
|
3298
3556
|
proxyTestState.textContent = `${res.proxy}\uFF1A${parts.join(" \xB7 ")}`;
|
|
3299
3557
|
};
|
|
3558
|
+
const persistProxyScope = async (partial) => {
|
|
3559
|
+
const res = await rpc("/config", { method: "POST", body: { proxyScopes: partial } });
|
|
3560
|
+
if (!res.ok) {
|
|
3561
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3562
|
+
return false;
|
|
3563
|
+
}
|
|
3564
|
+
if (res.config && res.config.proxyScopes) config.proxyScopes = res.config.proxyScopes;
|
|
3565
|
+
return true;
|
|
3566
|
+
};
|
|
3567
|
+
const proxyScopeWrap = h("div");
|
|
3568
|
+
const renderProxyScopes = () => {
|
|
3569
|
+
const sc = config.proxyScopes || {};
|
|
3570
|
+
proxyScopeWrap.replaceChildren(
|
|
3571
|
+
settingRow(L.proxyScopePlugins, L.proxyScopePluginsDesc, sc.plugins !== false, async () => {
|
|
3572
|
+
const next = !(sc.plugins !== false);
|
|
3573
|
+
if (await persistProxyScope({ plugins: next })) sc.plugins = next;
|
|
3574
|
+
renderProxyScopes();
|
|
3575
|
+
}),
|
|
3576
|
+
settingRow(L.proxyScopeDeps, L.proxyScopeDepsDesc, sc.deps !== false, async () => {
|
|
3577
|
+
const next = !(sc.deps !== false);
|
|
3578
|
+
if (await persistProxyScope({ deps: next })) sc.deps = next;
|
|
3579
|
+
renderProxyScopes();
|
|
3580
|
+
}),
|
|
3581
|
+
settingRow(L.proxyScopeSync, L.proxyScopeSyncDesc, sc.sync === true, async () => {
|
|
3582
|
+
const next = !(sc.sync === true);
|
|
3583
|
+
if (await persistProxyScope({ sync: next })) sc.sync = next;
|
|
3584
|
+
renderProxyScopes();
|
|
3585
|
+
})
|
|
3586
|
+
);
|
|
3587
|
+
};
|
|
3588
|
+
renderProxyScopes();
|
|
3300
3589
|
paneProxy.append(
|
|
3301
3590
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.proxyDesc),
|
|
3302
3591
|
h(
|
|
@@ -3307,7 +3596,8 @@
|
|
|
3307
3596
|
proxyTestBtn
|
|
3308
3597
|
),
|
|
3309
3598
|
h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" }, L.proxyHint),
|
|
3310
|
-
proxyTestState
|
|
3599
|
+
proxyTestState,
|
|
3600
|
+
h("div", { class: "mt-3 divide-y divide-border rounded-xl border border-border" }, proxyScopeWrap)
|
|
3311
3601
|
);
|
|
3312
3602
|
const perfToggleWrap = h("div");
|
|
3313
3603
|
const renderPerfToggle = () => {
|
|
@@ -3414,6 +3704,43 @@
|
|
|
3414
3704
|
syncCheckDirty();
|
|
3415
3705
|
}
|
|
3416
3706
|
};
|
|
3707
|
+
const syncTestState = h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" });
|
|
3708
|
+
let syncTesting = false;
|
|
3709
|
+
const syncTestBtn = btnSmall(L.syncTest, () => {
|
|
3710
|
+
void runSyncTest();
|
|
3711
|
+
}, "shrink-0");
|
|
3712
|
+
const runSyncTest = async () => {
|
|
3713
|
+
if (syncTesting) return;
|
|
3714
|
+
if (!syncUrlInput.value.trim()) {
|
|
3715
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-amber-500";
|
|
3716
|
+
syncTestState.textContent = L.syncTestEmpty;
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3719
|
+
syncTesting = true;
|
|
3720
|
+
syncTestBtn.disabled = true;
|
|
3721
|
+
syncTestBtn.textContent = L.syncTesting;
|
|
3722
|
+
syncTestState.textContent = "";
|
|
3723
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-foreground-subtle";
|
|
3724
|
+
const res = await rpc("/sync/test", { method: "POST", body: { sync: syncFormValues() } });
|
|
3725
|
+
syncTesting = false;
|
|
3726
|
+
syncTestBtn.disabled = false;
|
|
3727
|
+
syncTestBtn.textContent = L.syncTest;
|
|
3728
|
+
if (!res.ok) {
|
|
3729
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed text-destructive";
|
|
3730
|
+
syncTestState.textContent = L.syncTestFailed + ": " + errText(res);
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
const stepName = { connect: L.syncTestStepConnect, dir: L.syncTestStepDir, list: L.syncTestStepList };
|
|
3734
|
+
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());
|
|
3735
|
+
const allOk = (res.targets || []).length > 0 && (res.targets || []).every((t2) => t2.ok);
|
|
3736
|
+
let host = syncUrlInput.value.trim();
|
|
3737
|
+
try {
|
|
3738
|
+
host = new URL(host).host;
|
|
3739
|
+
} catch {
|
|
3740
|
+
}
|
|
3741
|
+
syncTestState.className = "mt-2 text-ui-xs/relaxed " + (allOk ? "text-foreground-subtle" : "text-amber-500");
|
|
3742
|
+
syncTestState.textContent = `${host}\uFF1A${parts.join(" \xB7 ")}` + (allOk && res.fileCount != null ? `\uFF08${L.syncTestFilesFound.replace("{n}", res.fileCount)}\uFF09` : "");
|
|
3743
|
+
};
|
|
3417
3744
|
const JIANGUO_HELP = "https://help.jianguoyun.com/?p=2064";
|
|
3418
3745
|
const syncRecLine = h("p", { class: "mt-1 text-ui-xs/relaxed text-foreground-subtle" });
|
|
3419
3746
|
if (typeof window.zcode?.openExternal === "function") {
|
|
@@ -3457,56 +3784,216 @@
|
|
|
3457
3784
|
};
|
|
3458
3785
|
renderSyncStatus(savedSync);
|
|
3459
3786
|
const syncUploadBtn = btnSmall(L.syncUpload, () => {
|
|
3460
|
-
void
|
|
3787
|
+
void runSyncPush();
|
|
3461
3788
|
}, "shrink-0", "primary");
|
|
3462
3789
|
const syncDownloadBtn = btnSmall(L.syncDownload, () => {
|
|
3463
|
-
|
|
3790
|
+
openSyncVersionPicker();
|
|
3464
3791
|
}, "shrink-0");
|
|
3465
|
-
const
|
|
3792
|
+
const openSyncVersionPicker = () => {
|
|
3466
3793
|
openDialog({
|
|
3467
|
-
title: L.
|
|
3468
|
-
description: L.
|
|
3469
|
-
width: "
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3794
|
+
title: L.syncPickTitle,
|
|
3795
|
+
description: L.syncPickDesc,
|
|
3796
|
+
width: "max-w-2xl",
|
|
3797
|
+
dismissOnOutside: false,
|
|
3798
|
+
onMount: async ({ body: pickBody, content: content2, close: closePicker }) => {
|
|
3799
|
+
const titleEl2 = content2 && content2.firstElementChild;
|
|
3800
|
+
if (titleEl2 && titleEl2.tagName === "H2") {
|
|
3801
|
+
titleEl2.classList.add("flex", "w-full", "items-center", "justify-between");
|
|
3802
|
+
titleEl2.replaceChildren(
|
|
3803
|
+
h("span", { class: "flex min-w-0 items-center" }, L.syncPickTitle),
|
|
3804
|
+
h("button", {
|
|
3805
|
+
type: "button",
|
|
3806
|
+
class: "zcodepro-close",
|
|
3807
|
+
title: L.close,
|
|
3808
|
+
"aria-label": L.close,
|
|
3809
|
+
onMousedown: (e) => {
|
|
3810
|
+
e.stopPropagation();
|
|
3811
|
+
},
|
|
3812
|
+
onClick: () => {
|
|
3813
|
+
closePicker();
|
|
3814
|
+
}
|
|
3815
|
+
}, "\u2715")
|
|
3816
|
+
);
|
|
3817
|
+
}
|
|
3818
|
+
const listWrap = h("div", { class: "space-y-1" });
|
|
3819
|
+
pickBody.append(listWrap);
|
|
3820
|
+
const fmtSize = (n) => {
|
|
3821
|
+
if (!Number.isFinite(n) || n <= 0) return "";
|
|
3822
|
+
return n >= 1048576 ? (n / 1048576).toFixed(2) + " MB" : Math.max(1, Math.round(n / 1024)) + " KB";
|
|
3823
|
+
};
|
|
3824
|
+
const setStatus = (el) => {
|
|
3825
|
+
listWrap.replaceChildren(el);
|
|
3826
|
+
};
|
|
3827
|
+
const setRowBusy = (btns, busy) => {
|
|
3828
|
+
for (const b of btns) b.disabled = busy;
|
|
3829
|
+
};
|
|
3830
|
+
const versionRow = (f) => {
|
|
3831
|
+
const isLatest = !/-\d{4}-\d{2}-\d{2}T/.test(f.name);
|
|
3832
|
+
const importBtn = btnSmall(L.syncVerImport, () => {
|
|
3833
|
+
confirmImport(f, rowBtns, importBtn);
|
|
3834
|
+
}, "shrink-0");
|
|
3835
|
+
const deleteBtn = btnSmall(L.syncVerDelete, () => {
|
|
3836
|
+
confirmDelete(f, rowBtns, isLatest);
|
|
3837
|
+
}, "shrink-0");
|
|
3838
|
+
const saveBtn = btnSmall(L.syncVerSave, () => {
|
|
3839
|
+
void exportVersion(f, rowBtns, saveBtn);
|
|
3840
|
+
}, "shrink-0");
|
|
3841
|
+
const rowBtns = [importBtn, deleteBtn, saveBtn];
|
|
3842
|
+
return h(
|
|
3843
|
+
"div",
|
|
3844
|
+
{ class: "flex items-center gap-3 rounded-xl border border-border px-3 py-2" },
|
|
3845
|
+
h(
|
|
3846
|
+
"div",
|
|
3847
|
+
{ class: "min-w-0 flex-1" },
|
|
3848
|
+
h(
|
|
3849
|
+
"div",
|
|
3850
|
+
{ class: "flex min-w-0 items-center gap-1.5" },
|
|
3851
|
+
h("span", { class: "truncate font-mono text-ui-xs text-foreground", title: f.name }, f.name),
|
|
3852
|
+
...isLatest ? [h("span", { class: "shrink-0 rounded border border-border px-1.5 text-ui-xs text-foreground-subtle" }, L.syncVerLatest)] : []
|
|
3853
|
+
),
|
|
3854
|
+
h(
|
|
3855
|
+
"div",
|
|
3856
|
+
{ class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" },
|
|
3857
|
+
[fmtSize(f.size), f.lastModified ? new Date(f.lastModified).toLocaleString() : ""].filter(Boolean).join(" \xB7 ")
|
|
3858
|
+
)
|
|
3859
|
+
),
|
|
3860
|
+
h("div", { class: "flex shrink-0 items-center gap-1.5" }, importBtn, deleteBtn, saveBtn)
|
|
3861
|
+
);
|
|
3862
|
+
};
|
|
3863
|
+
const loadList = async () => {
|
|
3864
|
+
setStatus(h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncPickLoading));
|
|
3865
|
+
const res = await rpc("/sync/versions", { method: "POST", body: {} });
|
|
3866
|
+
if (!res.ok) {
|
|
3867
|
+
setStatus(h("p", { class: "text-ui-sm text-destructive" }, L.failed + ": " + errText(res)));
|
|
3868
|
+
return;
|
|
3869
|
+
}
|
|
3870
|
+
const files = res.files || [];
|
|
3871
|
+
if (!files.length) {
|
|
3872
|
+
setStatus(h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncPickEmpty));
|
|
3873
|
+
return;
|
|
3874
|
+
}
|
|
3875
|
+
const parts = [];
|
|
3876
|
+
for (const [prefix, label] of [["zcodepro", L.syncIncludeZcp], ["model", L.syncIncludeModel]]) {
|
|
3877
|
+
const group = files.filter((f) => f.name === `${prefix}.json` || f.name.startsWith(`${prefix}-`));
|
|
3878
|
+
if (!group.length) continue;
|
|
3879
|
+
const latest = group.find((f) => f.name === `${prefix}.json`);
|
|
3880
|
+
const history = group.filter((f) => f !== latest).sort((a, b) => (b.lastModified || 0) - (a.lastModified || 0) || b.name.localeCompare(a.name));
|
|
3881
|
+
parts.push(h(
|
|
3882
|
+
"div",
|
|
3883
|
+
{ class: "px-1 pt-2 text-ui-xs font-medium text-foreground-subtle" },
|
|
3884
|
+
`${label}${isZhLocale() ? "\uFF08" : " ("}${group.length}${isZhLocale() ? "\uFF09" : ")"}`
|
|
3885
|
+
));
|
|
3886
|
+
for (const f of [latest, ...history]) {
|
|
3887
|
+
if (f) parts.push(versionRow(f));
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
listWrap.replaceChildren(...parts);
|
|
3891
|
+
};
|
|
3892
|
+
const confirmImport = (f, rowBtns, importBtn) => {
|
|
3893
|
+
openDialog({
|
|
3894
|
+
title: L.syncConfirmTitle,
|
|
3895
|
+
width: "sm:max-w-md",
|
|
3896
|
+
onMount: ({ body: confirmBody, close: closeConfirm }) => {
|
|
3897
|
+
confirmBody.append(
|
|
3898
|
+
h("p", { class: "mb-2 truncate font-mono text-ui-xs text-foreground-subtle", title: f.name }, f.name),
|
|
3899
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncConfirmDesc),
|
|
3900
|
+
dialogFooter(
|
|
3901
|
+
btnSecondary(L.cancel, () => closeConfirm()),
|
|
3902
|
+
btnPrimary(L.syncConfirmGo, () => {
|
|
3903
|
+
closeConfirm();
|
|
3904
|
+
void importVersion(f, rowBtns, importBtn);
|
|
3905
|
+
}, "min-w-24")
|
|
3906
|
+
)
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
});
|
|
3910
|
+
};
|
|
3911
|
+
const importVersion = async (f, rowBtns, importBtn) => {
|
|
3912
|
+
setRowBusy(rowBtns, true);
|
|
3913
|
+
importBtn.textContent = L.syncVerImporting;
|
|
3914
|
+
const res = await rpc("/sync/version/apply", { method: "POST", body: { file: f.name } });
|
|
3915
|
+
setRowBusy(rowBtns, false);
|
|
3916
|
+
importBtn.textContent = L.syncVerImport;
|
|
3917
|
+
if (!res.ok) {
|
|
3918
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3919
|
+
return;
|
|
3920
|
+
}
|
|
3921
|
+
closePicker();
|
|
3922
|
+
renderSyncStatus(res.sync || {});
|
|
3923
|
+
clearConfigCache();
|
|
3924
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
3925
|
+
Object.assign(config, await getConfig(true));
|
|
3926
|
+
refreshRows();
|
|
3927
|
+
renderToolbarSwitch();
|
|
3928
|
+
const names = (res.applied || []).map((k) => k === "model" ? L.syncIncludeModel : L.syncIncludeZcp).join(isZhLocale() ? "\u3001" : ", ");
|
|
3929
|
+
showToast(names ? `${L.syncDownloaded}\uFF08${names}\uFF09` : L.syncDownloaded, "success");
|
|
3930
|
+
};
|
|
3931
|
+
const confirmDelete = (f, rowBtns, isLatest) => {
|
|
3932
|
+
openDialog({
|
|
3933
|
+
title: L.syncVerDeleteTitle,
|
|
3934
|
+
width: "sm:max-w-md",
|
|
3935
|
+
onMount: ({ body: confirmBody, close: closeConfirm }) => {
|
|
3936
|
+
confirmBody.append(
|
|
3937
|
+
h(
|
|
3938
|
+
"p",
|
|
3939
|
+
{ class: "text-ui-sm/relaxed text-foreground-subtle" },
|
|
3940
|
+
L.syncVerDeleteDesc,
|
|
3941
|
+
h("span", { class: "font-mono" }, f.name)
|
|
3942
|
+
),
|
|
3943
|
+
...isLatest ? [h("p", { class: "mt-2 text-ui-xs/relaxed text-amber-500" }, L.syncVerDeleteLatestNote)] : [],
|
|
3944
|
+
dialogFooter(
|
|
3945
|
+
btnSecondary(L.cancel, () => closeConfirm()),
|
|
3946
|
+
btnPrimary(L.syncVerDelete, () => {
|
|
3947
|
+
closeConfirm();
|
|
3948
|
+
void deleteVersion(f, rowBtns);
|
|
3949
|
+
}, "min-w-24")
|
|
3950
|
+
)
|
|
3951
|
+
);
|
|
3952
|
+
}
|
|
3953
|
+
});
|
|
3954
|
+
};
|
|
3955
|
+
const deleteVersion = async (f, rowBtns) => {
|
|
3956
|
+
setRowBusy(rowBtns, true);
|
|
3957
|
+
const res = await rpc("/sync/version/delete", { method: "POST", body: { file: f.name } });
|
|
3958
|
+
setRowBusy(rowBtns, false);
|
|
3959
|
+
if (!res.ok) {
|
|
3960
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
3961
|
+
return;
|
|
3962
|
+
}
|
|
3963
|
+
showToast(L.syncVerDeleted, "success");
|
|
3964
|
+
void loadList();
|
|
3965
|
+
};
|
|
3966
|
+
const exportVersion = async (f, rowBtns, saveBtn) => {
|
|
3967
|
+
setRowBusy(rowBtns, true);
|
|
3968
|
+
saveBtn.textContent = L.syncVerSaving;
|
|
3969
|
+
const res = await rpc("/sync/version/export", { method: "POST", body: { file: f.name } });
|
|
3970
|
+
setRowBusy(rowBtns, false);
|
|
3971
|
+
saveBtn.textContent = L.syncVerSave;
|
|
3972
|
+
if (!res.ok) {
|
|
3973
|
+
if (res.code !== "export-cancelled") showToast(L.failed + ": " + errText(res), "error");
|
|
3974
|
+
return;
|
|
3975
|
+
}
|
|
3976
|
+
showToast(`${L.syncVerSaved} ${res.path}`, "success");
|
|
3977
|
+
};
|
|
3978
|
+
void loadList();
|
|
3480
3979
|
}
|
|
3481
3980
|
});
|
|
3482
3981
|
};
|
|
3483
|
-
const
|
|
3982
|
+
const runSyncPush = async () => {
|
|
3484
3983
|
syncUploadBtn.disabled = true;
|
|
3485
3984
|
syncDownloadBtn.disabled = true;
|
|
3486
|
-
const
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
const res = await rpc("/sync/run", { method: "POST", body: { direction } });
|
|
3985
|
+
const idleText = syncUploadBtn.textContent;
|
|
3986
|
+
syncUploadBtn.textContent = L.syncUploading;
|
|
3987
|
+
const res = await rpc("/sync/run", { method: "POST", body: { direction: "push" } });
|
|
3490
3988
|
syncUploadBtn.disabled = false;
|
|
3491
3989
|
syncDownloadBtn.disabled = false;
|
|
3492
|
-
|
|
3990
|
+
syncUploadBtn.textContent = idleText;
|
|
3493
3991
|
if (!res.ok) {
|
|
3494
3992
|
showToast(L.failed + ": " + errText(res), "error");
|
|
3495
3993
|
return;
|
|
3496
3994
|
}
|
|
3497
3995
|
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
|
-
}
|
|
3996
|
+
showToast(L.syncUploaded, "success");
|
|
3510
3997
|
};
|
|
3511
3998
|
paneSync.append(
|
|
3512
3999
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.syncDesc),
|
|
@@ -3526,9 +4013,10 @@
|
|
|
3526
4013
|
h("p", { class: "text-ui-xs/relaxed text-foreground-subtle" }, L.syncFormHint),
|
|
3527
4014
|
syncRecLine
|
|
3528
4015
|
),
|
|
3529
|
-
syncSaveBtn
|
|
4016
|
+
h("div", { class: "flex shrink-0 items-center gap-1.5" }, syncSaveBtn, syncTestBtn)
|
|
3530
4017
|
)
|
|
3531
4018
|
),
|
|
4019
|
+
syncTestState,
|
|
3532
4020
|
h("div", { class: "mt-2 divide-y divide-border rounded-xl border border-border" }, syncIncludeWrap),
|
|
3533
4021
|
h(
|
|
3534
4022
|
"div",
|
|
@@ -3538,6 +4026,59 @@
|
|
|
3538
4026
|
),
|
|
3539
4027
|
h("p", { class: "mt-2 text-ui-xs/relaxed text-foreground-subtle" }, L.syncHint)
|
|
3540
4028
|
);
|
|
4029
|
+
const persistDevMode = async (v) => {
|
|
4030
|
+
const res = await rpc("/config", { method: "POST", body: { devMode: v } });
|
|
4031
|
+
if (!res.ok) {
|
|
4032
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4033
|
+
return false;
|
|
4034
|
+
}
|
|
4035
|
+
if (res.config) config.devMode = res.config.devMode;
|
|
4036
|
+
return true;
|
|
4037
|
+
};
|
|
4038
|
+
const devReloadBtn = btnSmall(L.devReload, () => {
|
|
4039
|
+
void runDevReload();
|
|
4040
|
+
}, "shrink-0", "primary");
|
|
4041
|
+
const runDevReload = async () => {
|
|
4042
|
+
devReloadBtn.disabled = true;
|
|
4043
|
+
devReloadBtn.textContent = L.devReloading;
|
|
4044
|
+
try {
|
|
4045
|
+
await rpc("/dev/reload", { method: "POST", body: {} });
|
|
4046
|
+
} catch {
|
|
4047
|
+
}
|
|
4048
|
+
setTimeout(() => {
|
|
4049
|
+
try {
|
|
4050
|
+
location.reload();
|
|
4051
|
+
} catch {
|
|
4052
|
+
}
|
|
4053
|
+
}, 2e3);
|
|
4054
|
+
};
|
|
4055
|
+
const devModeWrap = h("div");
|
|
4056
|
+
const renderDevPane = () => {
|
|
4057
|
+
const dev = config.devMode === true;
|
|
4058
|
+
devModeWrap.replaceChildren(
|
|
4059
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.devModeDesc),
|
|
4060
|
+
h(
|
|
4061
|
+
"div",
|
|
4062
|
+
{ class: "mt-3 divide-y divide-border rounded-xl border border-border" },
|
|
4063
|
+
settingRow(L.devMode, L.devModeRowDesc, dev, async () => {
|
|
4064
|
+
if (await persistDevMode(!dev)) renderDevPane();
|
|
4065
|
+
}),
|
|
4066
|
+
...dev ? [h(
|
|
4067
|
+
"div",
|
|
4068
|
+
{ class: "flex items-center justify-between gap-2 px-2 py-1.5" },
|
|
4069
|
+
h(
|
|
4070
|
+
"div",
|
|
4071
|
+
{ class: "min-w-0" },
|
|
4072
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.devReload),
|
|
4073
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" }, L.devReloadDesc)
|
|
4074
|
+
),
|
|
4075
|
+
devReloadBtn
|
|
4076
|
+
)] : []
|
|
4077
|
+
)
|
|
4078
|
+
);
|
|
4079
|
+
};
|
|
4080
|
+
renderDevPane();
|
|
4081
|
+
paneDebug.append(devModeWrap);
|
|
3541
4082
|
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
4083
|
const VISION_DEFAULT_CFG = {
|
|
3543
4084
|
enabled: true,
|
|
@@ -3555,7 +4096,6 @@
|
|
|
3555
4096
|
skipMinutes: 30,
|
|
3556
4097
|
forceIntercept: true
|
|
3557
4098
|
};
|
|
3558
|
-
const visionProviders = visionProvidersRes.ok && Array.isArray(visionProvidersRes.providers) ? visionProvidersRes.providers : [];
|
|
3559
4099
|
let visionCfg = visionRes.ok && visionRes.config && typeof visionRes.config === "object" ? structuredClone(visionRes.config) : null;
|
|
3560
4100
|
let visionSaveTimer = null;
|
|
3561
4101
|
const persistVision = async () => {
|
|
@@ -3575,7 +4115,57 @@
|
|
|
3575
4115
|
style: "display:none"
|
|
3576
4116
|
});
|
|
3577
4117
|
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";
|
|
4118
|
+
const pluginInstallCard = (pluginName, onInstalled) => {
|
|
4119
|
+
const installBtn = btnSmall(L.headroomInstall, () => {
|
|
4120
|
+
void runInstall();
|
|
4121
|
+
}, "shrink-0");
|
|
4122
|
+
const installState = h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" });
|
|
4123
|
+
const runInstall = async () => {
|
|
4124
|
+
installBtn.disabled = true;
|
|
4125
|
+
installBtn.textContent = L.headroomInstalling;
|
|
4126
|
+
installState.textContent = "";
|
|
4127
|
+
const res = await rpc("/plugins/update", { method: "POST", body: { name: pluginName } });
|
|
4128
|
+
if (!res.ok) {
|
|
4129
|
+
installBtn.disabled = false;
|
|
4130
|
+
installBtn.textContent = L.headroomInstall;
|
|
4131
|
+
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
4132
|
+
return;
|
|
4133
|
+
}
|
|
4134
|
+
if (onInstalled) await onInstalled();
|
|
4135
|
+
showToast(L.pluginInstallDone.replaceAll("{name}", pluginName), "success");
|
|
4136
|
+
};
|
|
4137
|
+
return h(
|
|
4138
|
+
"div",
|
|
4139
|
+
{ class: "mt-3 flex items-center justify-between gap-2 rounded-xl border border-border p-2" },
|
|
4140
|
+
h(
|
|
4141
|
+
"div",
|
|
4142
|
+
{ class: "min-w-0" },
|
|
4143
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.pluginInstallCardTitle.replaceAll("{name}", pluginName)),
|
|
4144
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" }, L.pluginInstallCardDesc),
|
|
4145
|
+
installState
|
|
4146
|
+
),
|
|
4147
|
+
installBtn
|
|
4148
|
+
);
|
|
4149
|
+
};
|
|
3578
4150
|
const renderVision = () => {
|
|
4151
|
+
if (!visionRes.ok) {
|
|
4152
|
+
paneVision.replaceChildren(
|
|
4153
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
4154
|
+
h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.visionLoadFailed + ": " + errText(visionRes))
|
|
4155
|
+
);
|
|
4156
|
+
return;
|
|
4157
|
+
}
|
|
4158
|
+
if (!visionRes.hook) {
|
|
4159
|
+
paneVision.replaceChildren(
|
|
4160
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
4161
|
+
pluginInstallCard("zcode-vision", async () => {
|
|
4162
|
+
const meta = await rpc("/vision");
|
|
4163
|
+
if (meta.ok) Object.assign(visionRes, meta);
|
|
4164
|
+
renderVision();
|
|
4165
|
+
})
|
|
4166
|
+
);
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
3579
4169
|
if (!visionCfg) {
|
|
3580
4170
|
const initBtn = btnSmall(L.visionAddProxy, async () => {
|
|
3581
4171
|
const res = await rpc("/vision", { method: "POST", body: { config: VISION_DEFAULT_CFG } });
|
|
@@ -3587,6 +4177,16 @@
|
|
|
3587
4177
|
paneVision.replaceChildren(
|
|
3588
4178
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
3589
4179
|
...visionRes.ok ? [] : [h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.visionLoadFailed + ": " + errText(visionRes))],
|
|
4180
|
+
// 信息卡(仅版本行;配置未建,启用开关随配置出现)
|
|
4181
|
+
h(
|
|
4182
|
+
"div",
|
|
4183
|
+
{ class: "mt-3 rounded-xl border border-border p-2" },
|
|
4184
|
+
h(
|
|
4185
|
+
"div",
|
|
4186
|
+
{ class: "flex flex-wrap items-center gap-2" },
|
|
4187
|
+
h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" }, `\u63D2\u4EF6 ${visionRes.pluginVersion || "\u2014"}`)
|
|
4188
|
+
)
|
|
4189
|
+
),
|
|
3590
4190
|
h("div", { class: "mt-3 flex justify-end" }, initBtn)
|
|
3591
4191
|
);
|
|
3592
4192
|
return;
|
|
@@ -3687,53 +4287,45 @@
|
|
|
3687
4287
|
h(
|
|
3688
4288
|
"div",
|
|
3689
4289
|
{ class: "mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2" },
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
const cur = (p.useProvider || "").trim();
|
|
3698
|
-
const opts = [h("option", { value: "" }, L.visionUseProviderNone), h("option", { value: "session" }, L.visionUseProviderSession)];
|
|
3699
|
-
for (const pr of visionProviders) {
|
|
3700
|
-
opts.push(h("option", { value: pr.id }, pr.name && pr.name !== pr.id ? `${pr.name}\uFF08${pr.id}\uFF09` : pr.id));
|
|
3701
|
-
}
|
|
3702
|
-
if (cur && !opts.some((o) => o.value === cur)) opts.push(h("option", { value: cur }, `${cur}\uFF08${L.visionUseProvider}\uFF09`));
|
|
3703
|
-
sel.replaceChildren(...opts);
|
|
3704
|
-
sel.value = cur;
|
|
3705
|
-
};
|
|
3706
|
-
sel.addEventListener("change", () => {
|
|
3707
|
-
input.value = sel.value;
|
|
3708
|
-
p.useProvider = sel.value.trim();
|
|
3709
|
-
warn.style.display = "none";
|
|
4290
|
+
// 供应商与模型走 provider-fields 共用逻辑:跟随会话时模型下拉为
|
|
4291
|
+
// 全部供应商模型汇总,具体供应商为其模型列表;已删 id 标注「已删除」
|
|
4292
|
+
field(L.visionUseProvider, comboField(
|
|
4293
|
+
p.useProvider || "",
|
|
4294
|
+
providerOptionsOf(titleGenProviders, L),
|
|
4295
|
+
(v, src) => {
|
|
4296
|
+
p.useProvider = v;
|
|
3710
4297
|
saveVisionSoon();
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
4298
|
+
if (src === "select") renderVision();
|
|
4299
|
+
},
|
|
4300
|
+
{ placeholder: L.titleGenProviderSession, staleLabel: L.titleGenProviderDeleted }
|
|
4301
|
+
)),
|
|
4302
|
+
// 跟随会话时模型下拉头部有「跟随当前会话当前模型」(值为空,
|
|
4303
|
+
// 插件 ≥1.6.1 在调用时解析为会话当前模型);具体供应商为其模型列表
|
|
4304
|
+
field(L.visionModel, comboField(
|
|
4305
|
+
p.model || "",
|
|
4306
|
+
modelOptionsOf(p.useProvider, titleGenProviders, {
|
|
4307
|
+
followSession: (p.useProvider || "").trim() === "session",
|
|
4308
|
+
followSessionLabel: L.titleGenModelFollowSession
|
|
4309
|
+
}),
|
|
4310
|
+
(v) => {
|
|
4311
|
+
p.model = v;
|
|
3714
4312
|
saveVisionSoon();
|
|
3715
|
-
}
|
|
3716
|
-
|
|
3717
|
-
p.useProvider
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
p.
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
saveVisionSoon();
|
|
3732
|
-
})),
|
|
3733
|
-
field(L.visionApiKey + " \xB7 " + L.visionApiKeyHint, textIn(p.apiKey, (v) => {
|
|
3734
|
-
p.apiKey = v;
|
|
3735
|
-
saveVisionSoon();
|
|
3736
|
-
}, { type: "password" }))
|
|
4313
|
+
},
|
|
4314
|
+
{
|
|
4315
|
+
placeholder: modelPlaceholderOf(p.useProvider, L),
|
|
4316
|
+
emptyLabel: (p.useProvider || "").trim() === "session" ? L.titleGenModelFollowSession : L.titleGenModelEmpty
|
|
4317
|
+
}
|
|
4318
|
+
)),
|
|
4319
|
+
...isManualConn(p.useProvider, titleGenProviders) ? [
|
|
4320
|
+
field(L.visionBaseUrl, textIn(p.baseUrl, (v) => {
|
|
4321
|
+
p.baseUrl = v;
|
|
4322
|
+
saveVisionSoon();
|
|
4323
|
+
})),
|
|
4324
|
+
field(L.visionApiKey + " \xB7 " + L.visionApiKeyHint, textIn(p.apiKey, (v) => {
|
|
4325
|
+
p.apiKey = v;
|
|
4326
|
+
saveVisionSoon();
|
|
4327
|
+
}, { type: "password" }))
|
|
4328
|
+
] : []
|
|
3737
4329
|
),
|
|
3738
4330
|
(() => {
|
|
3739
4331
|
const n = h("textarea", { class: "zcodepro-textarea zcodepro-textarea-sm", rows: "3", placeholder: L.visionPrompt });
|
|
@@ -3759,7 +4351,26 @@
|
|
|
3759
4351
|
});
|
|
3760
4352
|
paneVision.replaceChildren(
|
|
3761
4353
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.visionDesc),
|
|
3762
|
-
//
|
|
4354
|
+
// 信息卡:插件版本 + 启用图片识别开关(与 rtk/headroom 面板同款式)
|
|
4355
|
+
h(
|
|
4356
|
+
"div",
|
|
4357
|
+
{ class: "mt-3 rounded-xl border border-border p-2" },
|
|
4358
|
+
h(
|
|
4359
|
+
"div",
|
|
4360
|
+
{ class: "flex flex-wrap items-center gap-2" },
|
|
4361
|
+
h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" }, `\u63D2\u4EF6 ${visionRes.pluginVersion || "\u2014"}`),
|
|
4362
|
+
h(
|
|
4363
|
+
"div",
|
|
4364
|
+
{ class: "ml-auto" },
|
|
4365
|
+
settingRow(L.visionEnabled, "", visionCfg.enabled !== false, async () => {
|
|
4366
|
+
visionCfg.enabled = !(visionCfg.enabled !== false);
|
|
4367
|
+
await persistVision();
|
|
4368
|
+
renderVision();
|
|
4369
|
+
})
|
|
4370
|
+
)
|
|
4371
|
+
)
|
|
4372
|
+
),
|
|
4373
|
+
// 链模式 + 强制拦截开关合到一行(启用开关已上移信息卡)
|
|
3763
4374
|
h(
|
|
3764
4375
|
"div",
|
|
3765
4376
|
{ class: "mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5 rounded-xl border border-border p-1" },
|
|
@@ -3769,11 +4380,6 @@
|
|
|
3769
4380
|
h(
|
|
3770
4381
|
"div",
|
|
3771
4382
|
{ 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
4383
|
settingRow(L.visionForceIntercept, "", visionCfg.forceIntercept !== false, async () => {
|
|
3778
4384
|
visionCfg.forceIntercept = !(visionCfg.forceIntercept !== false);
|
|
3779
4385
|
await persistVision();
|
|
@@ -3855,13 +4461,16 @@
|
|
|
3855
4461
|
};
|
|
3856
4462
|
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
4463
|
const rtkVersionLine = h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" });
|
|
4464
|
+
let rtkLocText = "";
|
|
3858
4465
|
const renderRtkVersion = (meta) => {
|
|
3859
|
-
const v = meta.version || "rtk";
|
|
3860
|
-
rtkVersionLine.textContent = meta.
|
|
4466
|
+
const v = String(meta.version || "").replace(/^rtk\s+/i, "").trim();
|
|
4467
|
+
rtkVersionLine.textContent = `\u63D2\u4EF6 ${meta.pluginVersion || "\u2014"}${v ? ` \xB7 rtk ${v}` : ""}`;
|
|
4468
|
+
rtkLocText = meta.binPath || "";
|
|
3861
4469
|
};
|
|
3862
4470
|
renderRtkVersion(rtkRes);
|
|
3863
4471
|
const rtkUp = makeUpgradeControls({
|
|
3864
4472
|
endpoint: "/rtk",
|
|
4473
|
+
idleText: () => rtkLocText,
|
|
3865
4474
|
metaRefresh: async () => {
|
|
3866
4475
|
const meta = await rpc("/rtk");
|
|
3867
4476
|
if (meta.ok) {
|
|
@@ -3874,19 +4483,49 @@
|
|
|
3874
4483
|
const rtkSwitchRow = h("div");
|
|
3875
4484
|
const rtkVersionCard = h(
|
|
3876
4485
|
"div",
|
|
3877
|
-
{ class: "mt-3 flex items-center gap-2 rounded-xl border border-border p-2" },
|
|
4486
|
+
{ class: "mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border p-2" },
|
|
3878
4487
|
rtkVersionLine,
|
|
3879
4488
|
rtkUp.state,
|
|
3880
4489
|
rtkUp.btn,
|
|
3881
|
-
rtkSwitchRow
|
|
4490
|
+
h("div", { class: "ml-auto shrink-0" }, rtkSwitchRow)
|
|
3882
4491
|
);
|
|
3883
4492
|
const rtkBody = h("div");
|
|
4493
|
+
const rtkPluginRow = h("div");
|
|
4494
|
+
const renderRtkPluginRow = () => {
|
|
4495
|
+
rtkPluginRow.replaceChildren(...rtkRes.hook ? [] : [
|
|
4496
|
+
pluginInstallCard("rtk", async () => {
|
|
4497
|
+
const meta = await rpc("/rtk");
|
|
4498
|
+
if (meta.ok) {
|
|
4499
|
+
Object.assign(rtkRes, meta);
|
|
4500
|
+
renderRtkVersion(meta);
|
|
4501
|
+
rtkCfg = {
|
|
4502
|
+
installed: meta.installed !== false,
|
|
4503
|
+
version: meta.version || "",
|
|
4504
|
+
binPath: meta.binPath || "",
|
|
4505
|
+
mode: meta.mode === "off" ? "off" : "hint",
|
|
4506
|
+
whitelist: Array.isArray(meta.whitelist) ? [...meta.whitelist] : [],
|
|
4507
|
+
builtinGit: Array.isArray(meta.builtinGit) ? [...meta.builtinGit] : [],
|
|
4508
|
+
builtinPlain: Array.isArray(meta.builtinPlain) ? [...meta.builtinPlain] : []
|
|
4509
|
+
};
|
|
4510
|
+
}
|
|
4511
|
+
renderRtkPluginRow();
|
|
4512
|
+
renderRtk();
|
|
4513
|
+
})
|
|
4514
|
+
]);
|
|
4515
|
+
};
|
|
4516
|
+
renderRtkPluginRow();
|
|
3884
4517
|
paneRtk.append(
|
|
3885
4518
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.rtkDesc),
|
|
4519
|
+
rtkPluginRow,
|
|
3886
4520
|
rtkVersionCard,
|
|
3887
4521
|
rtkBody
|
|
3888
4522
|
);
|
|
3889
4523
|
const renderRtk = () => {
|
|
4524
|
+
if (rtkRes.ok && !rtkRes.hook) {
|
|
4525
|
+
rtkVersionCard.style.display = "none";
|
|
4526
|
+
rtkBody.replaceChildren();
|
|
4527
|
+
return;
|
|
4528
|
+
}
|
|
3890
4529
|
rtkVersionCard.style.display = rtkCfg && rtkCfg.installed ? "" : "none";
|
|
3891
4530
|
if (!rtkCfg) {
|
|
3892
4531
|
rtkBody.replaceChildren(
|
|
@@ -3932,7 +4571,55 @@
|
|
|
3932
4571
|
})
|
|
3933
4572
|
);
|
|
3934
4573
|
rtkBody.replaceChildren(
|
|
3935
|
-
...rtkCfg.installed ? [] : [h(
|
|
4574
|
+
...rtkCfg.installed ? [] : [h(
|
|
4575
|
+
"div",
|
|
4576
|
+
{ class: "flex items-center gap-2" },
|
|
4577
|
+
h("p", { class: "min-w-0 flex-1 text-ui-sm text-amber-500" }, L.rtkNotInstalled),
|
|
4578
|
+
// 一键安装本体:与“检查更新”同一条 helper 升级管线(未装则装到 ~/.local/bin)
|
|
4579
|
+
(() => {
|
|
4580
|
+
const b = btnSmall(L.rtkInstallBin, () => {
|
|
4581
|
+
void run();
|
|
4582
|
+
}, "shrink-0");
|
|
4583
|
+
const run = async () => {
|
|
4584
|
+
b.disabled = true;
|
|
4585
|
+
b.textContent = L.headroomInstalling;
|
|
4586
|
+
const res = await rpc("/rtk", { method: "POST", body: { upgrade: true } });
|
|
4587
|
+
if (!res.ok) {
|
|
4588
|
+
b.disabled = false;
|
|
4589
|
+
b.textContent = L.rtkInstallBin;
|
|
4590
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4591
|
+
return;
|
|
4592
|
+
}
|
|
4593
|
+
const done = await new Promise((resolve) => {
|
|
4594
|
+
const iv = setInterval(async () => {
|
|
4595
|
+
const s = await rpc("/rtk/upgrade");
|
|
4596
|
+
if (s.ok && s.upgrade && !s.upgrade.running) {
|
|
4597
|
+
clearInterval(iv);
|
|
4598
|
+
resolve(s.upgrade);
|
|
4599
|
+
}
|
|
4600
|
+
}, 1200);
|
|
4601
|
+
setTimeout(() => {
|
|
4602
|
+
clearInterval(iv);
|
|
4603
|
+
resolve(null);
|
|
4604
|
+
}, 10 * 60 * 1e3);
|
|
4605
|
+
});
|
|
4606
|
+
if (done && !done.error && done.version) {
|
|
4607
|
+
const meta = await rpc("/rtk");
|
|
4608
|
+
if (meta.ok) {
|
|
4609
|
+
Object.assign(rtkRes, meta);
|
|
4610
|
+
rtkCfg = { ...rtkCfg, installed: meta.installed !== false, version: meta.version || "", binPath: meta.binPath || "" };
|
|
4611
|
+
}
|
|
4612
|
+
showToast(L.rtkBinInstalled, "success");
|
|
4613
|
+
renderRtk();
|
|
4614
|
+
} else {
|
|
4615
|
+
b.disabled = false;
|
|
4616
|
+
b.textContent = L.rtkInstallBin;
|
|
4617
|
+
showToast(done && done.error || L.headroomInstallRetry, "error");
|
|
4618
|
+
}
|
|
4619
|
+
};
|
|
4620
|
+
return b;
|
|
4621
|
+
})()
|
|
4622
|
+
)],
|
|
3936
4623
|
h(
|
|
3937
4624
|
"div",
|
|
3938
4625
|
{ class: "mt-2 rounded-xl border border-border p-2" },
|
|
@@ -3989,15 +4676,16 @@
|
|
|
3989
4676
|
};
|
|
3990
4677
|
renderRtk();
|
|
3991
4678
|
const hrVersionLine = h("span", { class: "shrink-0 whitespace-nowrap text-ui-xs/relaxed text-foreground-subtle" });
|
|
4679
|
+
let hrLocText = "";
|
|
4680
|
+
const hrSwitchRow = h("div");
|
|
3992
4681
|
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`;
|
|
4682
|
+
hrVersionLine.textContent = `\u63D2\u4EF6 ${meta.pluginVersion || "\u2014"}${meta.version ? ` \xB7 headroom ${meta.version}` : ""}`;
|
|
4683
|
+
hrLocText = meta.binPath || "";
|
|
3997
4684
|
};
|
|
3998
4685
|
renderHrVersion(headroomRes);
|
|
3999
4686
|
const hrUp = makeUpgradeControls({
|
|
4000
4687
|
endpoint: "/headroom",
|
|
4688
|
+
idleText: () => hrLocText,
|
|
4001
4689
|
metaRefresh: async () => {
|
|
4002
4690
|
const meta = await rpc("/headroom");
|
|
4003
4691
|
if (meta.ok) {
|
|
@@ -4025,7 +4713,7 @@
|
|
|
4025
4713
|
installBtn.disabled = true;
|
|
4026
4714
|
installBtn.textContent = L.headroomInstalling;
|
|
4027
4715
|
installState.textContent = "";
|
|
4028
|
-
const res = await rpc("/plugins/update", { method: "POST", body: { name: "headroom"
|
|
4716
|
+
const res = await rpc("/plugins/update", { method: "POST", body: { name: "headroom" } });
|
|
4029
4717
|
if (!res.ok) {
|
|
4030
4718
|
installBtn.disabled = false;
|
|
4031
4719
|
installBtn.textContent = L.headroomInstall;
|
|
@@ -4036,6 +4724,7 @@
|
|
|
4036
4724
|
if (meta.ok) Object.assign(headroomRes, meta);
|
|
4037
4725
|
if (headroomRes.hook) {
|
|
4038
4726
|
showToast(L.headroomInstalled, "success");
|
|
4727
|
+
renderHrVersion(headroomRes);
|
|
4039
4728
|
renderHeadroomPane();
|
|
4040
4729
|
} else {
|
|
4041
4730
|
installBtn.disabled = false;
|
|
@@ -4065,17 +4754,60 @@
|
|
|
4065
4754
|
const hrRun = async (reqBody, warn) => {
|
|
4066
4755
|
if (hrBusy) return false;
|
|
4067
4756
|
hrBusy = true;
|
|
4068
|
-
const
|
|
4069
|
-
|
|
4757
|
+
const action = reqBody && reqBody.action;
|
|
4758
|
+
const isStart = action === "start" || action === "restart";
|
|
4759
|
+
const isStop = action === "stop";
|
|
4760
|
+
const rpcDone = rpc("/headroom", { method: "POST", body: reqBody });
|
|
4761
|
+
let timerIv = null;
|
|
4762
|
+
if (isStart || isStop) {
|
|
4763
|
+
const wantUp = isStart;
|
|
4764
|
+
const msg = action === "restart" ? L.hrRestarting : isStart ? L.hrStarting : L.hrStopping;
|
|
4765
|
+
const doneMsg = isStart ? L.hrStarted : L.hrStopped;
|
|
4766
|
+
const timeoutMs = isStart ? 90 * 1e3 : 30 * 1e3;
|
|
4767
|
+
const t0 = Date.now();
|
|
4768
|
+
const timerSpan = h("span", { class: "text-ui-sm text-foreground-subtle/70" }, msg + " (0s)");
|
|
4769
|
+
hrStatusLine.replaceChildren(timerSpan);
|
|
4770
|
+
timerIv = setInterval(() => {
|
|
4771
|
+
timerSpan.textContent = msg + ` (${Math.round((Date.now() - t0) / 1e3)}s)`;
|
|
4772
|
+
}, 1e3);
|
|
4773
|
+
void (async () => {
|
|
4774
|
+
const kick = await rpcDone;
|
|
4775
|
+
if (!kick.ok) return;
|
|
4776
|
+
while (Date.now() - t0 < timeoutMs) {
|
|
4777
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4778
|
+
const st = await rpc("/headroom/status");
|
|
4779
|
+
if (!st.ok) continue;
|
|
4780
|
+
const up = !!(st.status && st.status.up);
|
|
4781
|
+
if (up === wantUp) {
|
|
4782
|
+
clearInterval(timerIv);
|
|
4783
|
+
hrBusy = false;
|
|
4784
|
+
await hrRefresh();
|
|
4785
|
+
showToast(doneMsg, isStart ? "success" : void 0);
|
|
4786
|
+
return;
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
clearInterval(timerIv);
|
|
4790
|
+
hrBusy = false;
|
|
4791
|
+
if (isStart) showToast(L.hrStartTimeout, "error");
|
|
4792
|
+
void hrRefresh();
|
|
4793
|
+
})();
|
|
4794
|
+
}
|
|
4795
|
+
const res = await rpcDone;
|
|
4070
4796
|
if (!res.ok) {
|
|
4797
|
+
if (timerIv) clearInterval(timerIv);
|
|
4798
|
+
hrBusy = false;
|
|
4071
4799
|
showToast(L.failed + ": " + errText(res), "error");
|
|
4800
|
+
void hrRefresh();
|
|
4072
4801
|
return false;
|
|
4073
4802
|
}
|
|
4074
4803
|
if (res.config) Object.assign(hrCfg, res.config);
|
|
4075
4804
|
if (warn) showToast(warn);
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4805
|
+
if (!isStart && !isStop) {
|
|
4806
|
+
hrBusy = false;
|
|
4807
|
+
setTimeout(() => {
|
|
4808
|
+
void hrRefresh();
|
|
4809
|
+
}, 1200);
|
|
4810
|
+
}
|
|
4079
4811
|
return true;
|
|
4080
4812
|
};
|
|
4081
4813
|
const hrDevLabel = (v) => v == null ? "\u2014" : v === "auto" ? L.hrValAuto : v === "cpu" ? "CPU" : v;
|
|
@@ -4120,6 +4852,23 @@
|
|
|
4120
4852
|
hrHintLine.textContent = s.saverHint || "";
|
|
4121
4853
|
hrHintLine.style.display = s.saverHint ? "" : "none";
|
|
4122
4854
|
};
|
|
4855
|
+
const renderHrUsageSwitch = () => {
|
|
4856
|
+
const usageOn = !!(headroomRes.usage && headroomRes.usage.enabled);
|
|
4857
|
+
hrSwitchRow.replaceChildren(
|
|
4858
|
+
settingRow(L.pluginEnable, "", usageOn, async () => {
|
|
4859
|
+
const next = !usageOn;
|
|
4860
|
+
const res = await rpc("/headroom", { method: "POST", body: { usage: next } });
|
|
4861
|
+
if (!res.ok) {
|
|
4862
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4863
|
+
return;
|
|
4864
|
+
}
|
|
4865
|
+
if (res.usage) headroomRes.usage = res.usage;
|
|
4866
|
+
renderHrUsageSwitch();
|
|
4867
|
+
if (next && !res.changed && !(res.usage && res.usage.enabled)) showToast(L.hrUsageNone);
|
|
4868
|
+
})
|
|
4869
|
+
);
|
|
4870
|
+
};
|
|
4871
|
+
renderHrUsageSwitch();
|
|
4123
4872
|
const hrRefreshBtn = btnSmall(L.headroomRefresh, () => {
|
|
4124
4873
|
void hrRefresh();
|
|
4125
4874
|
});
|
|
@@ -4212,14 +4961,69 @@
|
|
|
4212
4961
|
hrPwrHint.style.display = hrCfg.kompressBackend === "cpu" ? "" : "none";
|
|
4213
4962
|
};
|
|
4214
4963
|
updateHrPwrHint();
|
|
4964
|
+
const hrInstallBinBtn = (() => {
|
|
4965
|
+
const b = btnSmall(L.hrInstallBin, () => {
|
|
4966
|
+
void run();
|
|
4967
|
+
}, "shrink-0");
|
|
4968
|
+
let busy = false;
|
|
4969
|
+
const run = async () => {
|
|
4970
|
+
if (busy) return;
|
|
4971
|
+
busy = true;
|
|
4972
|
+
b.disabled = true;
|
|
4973
|
+
b.textContent = L.headroomInstalling;
|
|
4974
|
+
const res = await rpc("/headroom", { method: "POST", body: { upgrade: true } });
|
|
4975
|
+
if (!res.ok) {
|
|
4976
|
+
b.disabled = false;
|
|
4977
|
+
b.textContent = L.hrInstallBin;
|
|
4978
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4979
|
+
busy = false;
|
|
4980
|
+
return;
|
|
4981
|
+
}
|
|
4982
|
+
const done = await new Promise((resolve) => {
|
|
4983
|
+
const iv = setInterval(async () => {
|
|
4984
|
+
const s = await rpc("/headroom/upgrade");
|
|
4985
|
+
if (s.ok && s.upgrade && !s.upgrade.running) {
|
|
4986
|
+
clearInterval(iv);
|
|
4987
|
+
resolve(s.upgrade);
|
|
4988
|
+
}
|
|
4989
|
+
}, 2e3);
|
|
4990
|
+
setTimeout(() => {
|
|
4991
|
+
clearInterval(iv);
|
|
4992
|
+
resolve(null);
|
|
4993
|
+
}, 12 * 60 * 1e3);
|
|
4994
|
+
});
|
|
4995
|
+
busy = false;
|
|
4996
|
+
if (done && !done.error && done.version) {
|
|
4997
|
+
const meta = await rpc("/headroom");
|
|
4998
|
+
if (meta.ok) {
|
|
4999
|
+
renderHrVersion(meta);
|
|
5000
|
+
Object.assign(headroomRes, meta);
|
|
5001
|
+
}
|
|
5002
|
+
showToast(L.hrBinInstalled, "success");
|
|
5003
|
+
renderHeadroomPane();
|
|
5004
|
+
} else {
|
|
5005
|
+
b.disabled = false;
|
|
5006
|
+
b.textContent = L.hrInstallBin;
|
|
5007
|
+
showToast(done && done.error || L.headroomInstallRetry, "error");
|
|
5008
|
+
}
|
|
5009
|
+
};
|
|
5010
|
+
return b;
|
|
5011
|
+
})();
|
|
4215
5012
|
paneHeadroom.append(
|
|
4216
5013
|
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.headroomDesc),
|
|
4217
|
-
...headroomRes.installed === false ? [h(
|
|
5014
|
+
...headroomRes.installed === false ? [h(
|
|
5015
|
+
"div",
|
|
5016
|
+
{ class: "mt-2 flex items-center gap-2" },
|
|
5017
|
+
h("p", { class: "min-w-0 flex-1 text-ui-sm text-amber-500" }, L.headroomBinMissing),
|
|
5018
|
+
hrInstallBinBtn
|
|
5019
|
+
)] : [],
|
|
4218
5020
|
h(
|
|
4219
5021
|
"div",
|
|
4220
|
-
{ class: "mt-3 flex items-center
|
|
4221
|
-
|
|
4222
|
-
hrUp.
|
|
5022
|
+
{ class: "mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border p-2" },
|
|
5023
|
+
hrVersionLine,
|
|
5024
|
+
hrUp.state,
|
|
5025
|
+
hrUp.btn,
|
|
5026
|
+
h("div", { class: "ml-auto shrink-0" }, hrSwitchRow)
|
|
4223
5027
|
),
|
|
4224
5028
|
h(
|
|
4225
5029
|
"div",
|
|
@@ -4262,18 +5066,196 @@
|
|
|
4262
5066
|
);
|
|
4263
5067
|
};
|
|
4264
5068
|
renderHeadroomPane();
|
|
5069
|
+
let titleGenCfg = titleGenRes.ok && titleGenRes.titleGen && typeof titleGenRes.titleGen === "object" ? structuredClone(titleGenRes.titleGen) : null;
|
|
5070
|
+
const titleGenDefaultPrompt = titleGenRes.ok && typeof titleGenRes.defaultPrompt === "string" ? titleGenRes.defaultPrompt : "";
|
|
5071
|
+
let titleGenSaveTimer = null;
|
|
5072
|
+
const persistTitleGen = async () => {
|
|
5073
|
+
const res = await rpc("/title-gen", { method: "POST", body: { titleGen: titleGenCfg } });
|
|
5074
|
+
clearConfigCache();
|
|
5075
|
+
if (!res.ok) showToast(L.failed + ": " + errText(res), "error");
|
|
5076
|
+
return res.ok;
|
|
5077
|
+
};
|
|
5078
|
+
const saveTitleGenSoon = () => {
|
|
5079
|
+
clearTimeout(titleGenSaveTimer);
|
|
5080
|
+
titleGenSaveTimer = setTimeout(() => {
|
|
5081
|
+
void persistTitleGen();
|
|
5082
|
+
}, 500);
|
|
5083
|
+
};
|
|
5084
|
+
const renderTitleGenPane = () => {
|
|
5085
|
+
if (!titleGenCfg) {
|
|
5086
|
+
paneTitleGen.replaceChildren(
|
|
5087
|
+
h("p", { class: "text-ui-sm/relaxed text-foreground-subtle" }, L.titleGenShortDesc),
|
|
5088
|
+
h("p", { class: "mt-2 text-ui-sm text-destructive" }, L.visionLoadFailed + ": " + errText(titleGenRes))
|
|
5089
|
+
);
|
|
5090
|
+
return;
|
|
5091
|
+
}
|
|
5092
|
+
const inputCls = "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";
|
|
5093
|
+
const field = (labelText, node) => h(
|
|
5094
|
+
"label",
|
|
5095
|
+
{ class: "block min-w-0" },
|
|
5096
|
+
h("span", { class: "mb-1 block text-ui-xs font-medium text-foreground-subtle" }, labelText),
|
|
5097
|
+
node
|
|
5098
|
+
);
|
|
5099
|
+
const showInlineConn = isManualConn(titleGenCfg.provider, titleGenProviders);
|
|
5100
|
+
const providerCombo = comboField(
|
|
5101
|
+
titleGenCfg.provider || "",
|
|
5102
|
+
providerOptionsOf(titleGenProviders, L),
|
|
5103
|
+
(v, src) => {
|
|
5104
|
+
titleGenCfg.provider = v;
|
|
5105
|
+
if (src === "select") {
|
|
5106
|
+
void persistTitleGen();
|
|
5107
|
+
renderTitleGenPane();
|
|
5108
|
+
} else saveTitleGenSoon();
|
|
5109
|
+
},
|
|
5110
|
+
{ placeholder: L.titleGenProviderSession, staleLabel: L.titleGenProviderDeleted }
|
|
5111
|
+
);
|
|
5112
|
+
const modelCombo = comboField(
|
|
5113
|
+
titleGenCfg.model || "",
|
|
5114
|
+
// 跟随会话时选项表头部有“跟随当前会话当前模型”(值为空,生成时用
|
|
5115
|
+
// 会话当前模型),选了具体模型后也能再切回它
|
|
5116
|
+
modelOptionsOf(titleGenCfg.provider, titleGenProviders, {
|
|
5117
|
+
followSession: true,
|
|
5118
|
+
followSessionLabel: L.titleGenModelFollowSession
|
|
5119
|
+
}),
|
|
5120
|
+
(v) => {
|
|
5121
|
+
titleGenCfg.model = v;
|
|
5122
|
+
saveTitleGenSoon();
|
|
5123
|
+
},
|
|
5124
|
+
{
|
|
5125
|
+
placeholder: modelPlaceholderOf(titleGenCfg.provider, L),
|
|
5126
|
+
emptyLabel: (titleGenCfg.provider || "").trim() === "session" ? L.titleGenModelFollowSession : L.titleGenModelEmpty
|
|
5127
|
+
}
|
|
5128
|
+
);
|
|
5129
|
+
const textIn = (value, onInput, { type = "text", placeholder = "" } = {}) => {
|
|
5130
|
+
const n = h("input", { type, value: value || "", placeholder, class: inputCls });
|
|
5131
|
+
n.addEventListener("input", () => onInput(n.value));
|
|
5132
|
+
return n;
|
|
5133
|
+
};
|
|
5134
|
+
const formatSel = h(
|
|
5135
|
+
"select",
|
|
5136
|
+
{ class: inputCls },
|
|
5137
|
+
h("option", { value: "anthropic" }, "anthropic"),
|
|
5138
|
+
h("option", { value: "openai" }, "openai")
|
|
5139
|
+
);
|
|
5140
|
+
formatSel.value = titleGenCfg.format === "openai" ? "openai" : "anthropic";
|
|
5141
|
+
formatSel.addEventListener("change", () => {
|
|
5142
|
+
titleGenCfg.format = formatSel.value;
|
|
5143
|
+
void persistTitleGen();
|
|
5144
|
+
});
|
|
5145
|
+
const inlineConnCard = h(
|
|
5146
|
+
"div",
|
|
5147
|
+
{
|
|
5148
|
+
class: "mt-2 grid grid-cols-1 gap-2 rounded-xl border border-border p-2 sm:grid-cols-3",
|
|
5149
|
+
style: showInlineConn ? "" : "display:none"
|
|
5150
|
+
},
|
|
5151
|
+
field(L.titleGenBaseUrl, textIn(titleGenCfg.baseUrl, (v) => {
|
|
5152
|
+
titleGenCfg.baseUrl = v;
|
|
5153
|
+
saveTitleGenSoon();
|
|
5154
|
+
}, { placeholder: "https://\u2026" })),
|
|
5155
|
+
field(L.titleGenApiKey, textIn(titleGenCfg.apiKey, (v) => {
|
|
5156
|
+
titleGenCfg.apiKey = v;
|
|
5157
|
+
saveTitleGenSoon();
|
|
5158
|
+
}, { type: "password" })),
|
|
5159
|
+
field(L.titleGenFormat, formatSel)
|
|
5160
|
+
);
|
|
5161
|
+
const promptArea = h("textarea", {
|
|
5162
|
+
class: "zcodepro-textarea zcodepro-textarea-sm",
|
|
5163
|
+
rows: "8",
|
|
5164
|
+
placeholder: L.titleGenPromptPlaceholder
|
|
5165
|
+
});
|
|
5166
|
+
promptArea.value = titleGenCfg.prompt || "";
|
|
5167
|
+
promptArea.addEventListener("input", () => {
|
|
5168
|
+
titleGenCfg.prompt = promptArea.value;
|
|
5169
|
+
saveTitleGenSoon();
|
|
5170
|
+
});
|
|
5171
|
+
const sampleText = isZhLocale() ? "\u5E2E\u6211\u770B\u4E0B\u8FD9\u4E2A\u62A5\u9519\u662F\u4EC0\u4E48\u539F\u56E0\uFF1ANullPointerException at com.example.OrderService.calculate(OrderService.java:87)" : "Why does my Spring Boot app throw NullPointerException intermittently in OrderService.calculate?";
|
|
5172
|
+
const sampleInput = h("input", {
|
|
5173
|
+
type: "text",
|
|
5174
|
+
class: inputCls + " min-w-0 flex-1",
|
|
5175
|
+
value: sampleText
|
|
5176
|
+
});
|
|
5177
|
+
let testBtn;
|
|
5178
|
+
const testState = h("span", { class: "min-w-0 flex-1 truncate text-ui-xs/relaxed text-foreground-subtle" });
|
|
5179
|
+
testBtn = btnSmall(L.titleGenTest, async () => {
|
|
5180
|
+
testBtn.disabled = true;
|
|
5181
|
+
testBtn.textContent = L.titleGenTesting;
|
|
5182
|
+
testState.textContent = L.titleGenTesting;
|
|
5183
|
+
const res = await rpc("/title-gen/run", {
|
|
5184
|
+
method: "POST",
|
|
5185
|
+
body: { text: sampleInput.value, test: true }
|
|
5186
|
+
});
|
|
5187
|
+
testBtn.disabled = false;
|
|
5188
|
+
testBtn.textContent = L.titleGenTest;
|
|
5189
|
+
if (res && res.ok) {
|
|
5190
|
+
testState.textContent = L.titleGenTestOk + res.title;
|
|
5191
|
+
showToast(res.title, "success");
|
|
5192
|
+
} else {
|
|
5193
|
+
testState.textContent = res && errText(res) || L.titleGenTestFailed;
|
|
5194
|
+
testState.className = "min-w-0 flex-1 truncate text-ui-xs/relaxed text-destructive";
|
|
5195
|
+
showToast(L.titleGenTestFailed + ": " + (res ? errText(res) : ""), "error");
|
|
5196
|
+
}
|
|
5197
|
+
}, "shrink-0");
|
|
5198
|
+
paneTitleGen.replaceChildren(
|
|
5199
|
+
// 信息卡:一句话简介在左,启用开关右对齐
|
|
5200
|
+
h(
|
|
5201
|
+
"div",
|
|
5202
|
+
{ class: "mt-3 flex items-center justify-between gap-2 rounded-xl border border-border p-2" },
|
|
5203
|
+
h("span", { class: "min-w-0 text-ui-sm/relaxed text-foreground-subtle" }, L.titleGenShortDesc),
|
|
5204
|
+
h("div", { class: "shrink-0" }, settingRow(L.titleGenEnabled, "", titleGenCfg.enabled === true, async () => {
|
|
5205
|
+
titleGenCfg.enabled = !(titleGenCfg.enabled === true);
|
|
5206
|
+
await persistTitleGen();
|
|
5207
|
+
renderTitleGenPane();
|
|
5208
|
+
}))
|
|
5209
|
+
),
|
|
5210
|
+
// 供应商 + 模型
|
|
5211
|
+
h(
|
|
5212
|
+
"div",
|
|
5213
|
+
{ class: "mt-2 grid grid-cols-1 gap-2 rounded-xl border border-border p-2 sm:grid-cols-2" },
|
|
5214
|
+
field(L.titleGenProvider, providerCombo),
|
|
5215
|
+
field(L.titleGenModel, modelCombo)
|
|
5216
|
+
),
|
|
5217
|
+
inlineConnCard,
|
|
5218
|
+
// 提示词 + 载入默认
|
|
5219
|
+
h(
|
|
5220
|
+
"div",
|
|
5221
|
+
{ class: "mt-2 rounded-xl border border-border p-2" },
|
|
5222
|
+
h(
|
|
5223
|
+
"div",
|
|
5224
|
+
{ class: "mb-1 flex items-center justify-between gap-2" },
|
|
5225
|
+
h("span", { class: "text-ui-xs font-medium text-foreground-subtle" }, L.titleGenPrompt),
|
|
5226
|
+
btnSmall(L.titleGenPromptReset, () => {
|
|
5227
|
+
promptArea.value = titleGenDefaultPrompt;
|
|
5228
|
+
titleGenCfg.prompt = titleGenDefaultPrompt;
|
|
5229
|
+
void persistTitleGen();
|
|
5230
|
+
promptArea.focus();
|
|
5231
|
+
})
|
|
5232
|
+
),
|
|
5233
|
+
promptArea
|
|
5234
|
+
),
|
|
5235
|
+
// 测试
|
|
5236
|
+
h(
|
|
5237
|
+
"div",
|
|
5238
|
+
{ class: "mt-2 flex items-center gap-2 rounded-xl border border-border p-2" },
|
|
5239
|
+
sampleInput,
|
|
5240
|
+
testBtn
|
|
5241
|
+
),
|
|
5242
|
+
testState
|
|
5243
|
+
);
|
|
5244
|
+
};
|
|
5245
|
+
renderTitleGenPane();
|
|
4265
5246
|
body.append(
|
|
4266
5247
|
statusLine,
|
|
4267
5248
|
tablist,
|
|
4268
5249
|
paneFeatures,
|
|
5250
|
+
paneAgents,
|
|
4269
5251
|
paneStyles,
|
|
4270
5252
|
panePerf,
|
|
4271
|
-
paneAgents,
|
|
4272
5253
|
paneProxy,
|
|
4273
5254
|
paneSync,
|
|
4274
5255
|
paneVision,
|
|
4275
5256
|
paneHeadroom,
|
|
4276
|
-
paneRtk
|
|
5257
|
+
paneRtk,
|
|
5258
|
+
paneDebug
|
|
4277
5259
|
);
|
|
4278
5260
|
}
|
|
4279
5261
|
});
|
|
@@ -4740,6 +5722,16 @@
|
|
|
4740
5722
|
const map = await fetchPinned();
|
|
4741
5723
|
if (map) scan2();
|
|
4742
5724
|
}
|
|
5725
|
+
function setRowTitle(key, text) {
|
|
5726
|
+
for (const item of findRows(key)) {
|
|
5727
|
+
for (const el of titleElsOf(item)) writeTitle(el, text);
|
|
5728
|
+
}
|
|
5729
|
+
}
|
|
5730
|
+
function refreshPinnedTitles() {
|
|
5731
|
+
return fetchPinned().then((m) => {
|
|
5732
|
+
if (m) scan2();
|
|
5733
|
+
});
|
|
5734
|
+
}
|
|
4743
5735
|
function startTitleLock() {
|
|
4744
5736
|
if (installed2 || typeof document === "undefined") return;
|
|
4745
5737
|
installed2 = true;
|
|
@@ -4775,8 +5767,146 @@
|
|
|
4775
5767
|
});
|
|
4776
5768
|
}
|
|
4777
5769
|
|
|
4778
|
-
// src/inject/features/
|
|
5770
|
+
// src/inject/features/title-gen.js
|
|
5771
|
+
var CONV2 = '[class*="@md/conversation"]';
|
|
5772
|
+
var USER_ROW = '[class*="user-row"]';
|
|
5773
|
+
var SCAN_DEBOUNCE_MS3 = 300;
|
|
5774
|
+
var SCAN_FALLBACK_MS3 = 5e3;
|
|
5775
|
+
var SELECT_WAIT_MS = 2e3;
|
|
5776
|
+
var MSG_WAIT_MS = 1e4;
|
|
5777
|
+
var QUIET_FALLBACK_MS = 12e4;
|
|
5778
|
+
var COLLECT_MAX_MS = 6e5;
|
|
4779
5779
|
var installed3 = false;
|
|
5780
|
+
var knownKeys = /* @__PURE__ */ new Set();
|
|
5781
|
+
var attempted = /* @__PURE__ */ new Set();
|
|
5782
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
5783
|
+
function sessIdOf2(key) {
|
|
5784
|
+
const i = key.indexOf(":sess_");
|
|
5785
|
+
return i > 0 ? key.slice(i + 1) : "";
|
|
5786
|
+
}
|
|
5787
|
+
function currentKey() {
|
|
5788
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
5789
|
+
if ((el.className + "").includes("bg-selected")) return el.getAttribute("data-task-item-key") || "";
|
|
5790
|
+
}
|
|
5791
|
+
return "";
|
|
5792
|
+
}
|
|
5793
|
+
function userTexts() {
|
|
5794
|
+
return [...document.querySelectorAll(`${CONV2} ${USER_ROW}`)].map((r) => {
|
|
5795
|
+
const el = r.querySelector(".whitespace-pre-wrap");
|
|
5796
|
+
return ((el ? el.textContent : r.innerText) || "").trim();
|
|
5797
|
+
}).filter(Boolean);
|
|
5798
|
+
}
|
|
5799
|
+
async function onNewTaskRow(key) {
|
|
5800
|
+
const selDeadline = Date.now() + SELECT_WAIT_MS;
|
|
5801
|
+
while (currentKey() !== key && Date.now() < selDeadline) await sleep(200);
|
|
5802
|
+
if (currentKey() !== key) return;
|
|
5803
|
+
const cfg = await getConfig().catch(() => null);
|
|
5804
|
+
if (!cfg || !cfg.titleGen || cfg.titleGen.enabled !== true) return;
|
|
5805
|
+
const sessId = sessIdOf2(key);
|
|
5806
|
+
if (!sessId || attempted.has(sessId)) return;
|
|
5807
|
+
attempted.add(sessId);
|
|
5808
|
+
let texts = [];
|
|
5809
|
+
const msgDeadline = Date.now() + MSG_WAIT_MS;
|
|
5810
|
+
while (Date.now() < msgDeadline) {
|
|
5811
|
+
texts = userTexts();
|
|
5812
|
+
if (texts.length) break;
|
|
5813
|
+
await sleep(400);
|
|
5814
|
+
}
|
|
5815
|
+
if (!texts.length) return;
|
|
5816
|
+
let assistantSeen = false;
|
|
5817
|
+
const convObserver = new MutationObserver((muts) => {
|
|
5818
|
+
if (currentKey() !== key) return;
|
|
5819
|
+
for (const m of muts) {
|
|
5820
|
+
const t2 = m.type === "characterData" ? m.target.parentElement : m.target;
|
|
5821
|
+
if (t2 instanceof Element && t2.closest(USER_ROW)) continue;
|
|
5822
|
+
for (const n of [t2, ...m.addedNodes]) {
|
|
5823
|
+
if (n instanceof Element && n.closest && n.closest(CONV2)) {
|
|
5824
|
+
assistantSeen = true;
|
|
5825
|
+
return;
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
});
|
|
5830
|
+
convObserver.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
5831
|
+
const startAt = Date.now();
|
|
5832
|
+
let lastCount = texts.length;
|
|
5833
|
+
let lastChange = Date.now();
|
|
5834
|
+
try {
|
|
5835
|
+
while (Date.now() - startAt < COLLECT_MAX_MS) {
|
|
5836
|
+
await sleep(500);
|
|
5837
|
+
if (currentKey() !== key) {
|
|
5838
|
+
lastChange = Date.now();
|
|
5839
|
+
continue;
|
|
5840
|
+
}
|
|
5841
|
+
texts = userTexts();
|
|
5842
|
+
if (texts.length !== lastCount) {
|
|
5843
|
+
lastCount = texts.length;
|
|
5844
|
+
lastChange = Date.now();
|
|
5845
|
+
}
|
|
5846
|
+
if (assistantSeen) break;
|
|
5847
|
+
if (Date.now() - lastChange >= QUIET_FALLBACK_MS) break;
|
|
5848
|
+
}
|
|
5849
|
+
} finally {
|
|
5850
|
+
convObserver.disconnect();
|
|
5851
|
+
}
|
|
5852
|
+
if (!texts.length) return;
|
|
5853
|
+
const res = await rpc("/title-gen/run", { method: "POST", body: { sessId, text: texts.join("\n") } }).catch(() => null);
|
|
5854
|
+
if (res && res.ok && res.written && res.title) {
|
|
5855
|
+
setRowTitle(key, res.title);
|
|
5856
|
+
void refreshPinnedTitles();
|
|
5857
|
+
}
|
|
5858
|
+
}
|
|
5859
|
+
function scanForNewRows() {
|
|
5860
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
5861
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
5862
|
+
if (!key || knownKeys.has(key)) continue;
|
|
5863
|
+
knownKeys.add(key);
|
|
5864
|
+
void onNewTaskRow(key);
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
var TASK_SEL2 = "[data-task-item-key]";
|
|
5868
|
+
var inTaskRow3 = (node) => !!(node instanceof Element && node.closest && node.closest(TASK_SEL2));
|
|
5869
|
+
function taskRowMutations3(muts) {
|
|
5870
|
+
for (const m of muts) {
|
|
5871
|
+
if (m.type === "attributes") {
|
|
5872
|
+
if (inTaskRow3(m.target)) return true;
|
|
5873
|
+
} else if (m.type === "characterData") {
|
|
5874
|
+
if (m.target.parentElement && inTaskRow3(m.target.parentElement)) return true;
|
|
5875
|
+
} else if (inTaskRow3(m.target)) {
|
|
5876
|
+
return true;
|
|
5877
|
+
} else {
|
|
5878
|
+
for (const n of m.addedNodes) {
|
|
5879
|
+
if (n instanceof Element && (n.matches(TASK_SEL2) || !!n.querySelector(TASK_SEL2))) return true;
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
return false;
|
|
5884
|
+
}
|
|
5885
|
+
var scanDebounce3 = 0;
|
|
5886
|
+
function scheduleScan3() {
|
|
5887
|
+
if (scanDebounce3) return;
|
|
5888
|
+
scanDebounce3 = setTimeout(() => {
|
|
5889
|
+
scanDebounce3 = 0;
|
|
5890
|
+
scanForNewRows();
|
|
5891
|
+
}, SCAN_DEBOUNCE_MS3);
|
|
5892
|
+
}
|
|
5893
|
+
function startTitleGen() {
|
|
5894
|
+
if (installed3 || typeof document === "undefined") return;
|
|
5895
|
+
installed3 = true;
|
|
5896
|
+
scanForNewRows();
|
|
5897
|
+
new MutationObserver((muts) => {
|
|
5898
|
+
if (taskRowMutations3(muts)) scheduleScan3();
|
|
5899
|
+
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"], characterData: true });
|
|
5900
|
+
setInterval(() => {
|
|
5901
|
+
if (!document.hidden) scanForNewRows();
|
|
5902
|
+
}, SCAN_FALLBACK_MS3);
|
|
5903
|
+
document.addEventListener("visibilitychange", () => {
|
|
5904
|
+
if (!document.hidden) scanForNewRows();
|
|
5905
|
+
});
|
|
5906
|
+
}
|
|
5907
|
+
|
|
5908
|
+
// src/inject/features/pinned-expand.js
|
|
5909
|
+
var installed4 = false;
|
|
4780
5910
|
var keepCollapsed = false;
|
|
4781
5911
|
var CONFIG_POLL_MIN_MS = 5e3;
|
|
4782
5912
|
var CONFIG_POLL_MAX_MS = 6e4;
|
|
@@ -4803,8 +5933,8 @@
|
|
|
4803
5933
|
}, pollMs);
|
|
4804
5934
|
}
|
|
4805
5935
|
function startPinnedExpandSuppression() {
|
|
4806
|
-
if (
|
|
4807
|
-
|
|
5936
|
+
if (installed4 || typeof document === "undefined") return;
|
|
5937
|
+
installed4 = true;
|
|
4808
5938
|
void refreshConfig();
|
|
4809
5939
|
pollConfig();
|
|
4810
5940
|
document.addEventListener("visibilitychange", () => {
|
|
@@ -4883,10 +6013,10 @@
|
|
|
4883
6013
|
}
|
|
4884
6014
|
|
|
4885
6015
|
// src/inject/features/ws-running.js
|
|
4886
|
-
var
|
|
6016
|
+
var installed5 = false;
|
|
4887
6017
|
var enabled3 = true;
|
|
4888
|
-
var
|
|
4889
|
-
var
|
|
6018
|
+
var SCAN_DEBOUNCE_MS4 = 150;
|
|
6019
|
+
var SCAN_FALLBACK_MS4 = 5e3;
|
|
4890
6020
|
var PEEK_FIRST_MS = 2e4;
|
|
4891
6021
|
var PEEK_REPEAT_MS = 6e4;
|
|
4892
6022
|
var PEEK_SETTLE_MS = 160;
|
|
@@ -4894,7 +6024,7 @@
|
|
|
4894
6024
|
var PEEK_UNMOUNT_WAIT_MS = 800;
|
|
4895
6025
|
var CONFIG_POLL_MIN_MS2 = 5e3;
|
|
4896
6026
|
var CONFIG_POLL_MAX_MS2 = 6e4;
|
|
4897
|
-
var
|
|
6027
|
+
var TASK_SEL3 = "[data-task-item-key]";
|
|
4898
6028
|
var WS_SEL = '[data-testid^="workspace-item-"]';
|
|
4899
6029
|
var runningByWs = /* @__PURE__ */ new Map();
|
|
4900
6030
|
var peekTimers = /* @__PURE__ */ new Map();
|
|
@@ -4917,10 +6047,10 @@
|
|
|
4917
6047
|
return [...holder.children].some((c) => c.tagName === "svg" && (c.getAttribute("class") || "").includes("lucide-loader"));
|
|
4918
6048
|
}
|
|
4919
6049
|
function domRowsOf(ws) {
|
|
4920
|
-
return [...document.querySelectorAll(
|
|
6050
|
+
return [...document.querySelectorAll(TASK_SEL3)].filter((e) => workspaceOf2(e.getAttribute("data-task-item-key") || "") === ws);
|
|
4921
6051
|
}
|
|
4922
6052
|
function currentTaskRow2() {
|
|
4923
|
-
for (const el of document.querySelectorAll(
|
|
6053
|
+
for (const el of document.querySelectorAll(TASK_SEL3)) {
|
|
4924
6054
|
if ((el.className + "").includes("bg-selected")) return el;
|
|
4925
6055
|
}
|
|
4926
6056
|
return null;
|
|
@@ -4936,12 +6066,12 @@
|
|
|
4936
6066
|
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
4937
6067
|
synthClick(head);
|
|
4938
6068
|
if (!backKey) return;
|
|
4939
|
-
const back = cur && cur.isConnected ? cur : document.querySelector(`${
|
|
6069
|
+
const back = cur && cur.isConnected ? cur : document.querySelector(`${TASK_SEL3}[data-task-item-key="${CSS.escape(backKey)}"]`);
|
|
4940
6070
|
if (back) synthClick(back);
|
|
4941
6071
|
}
|
|
4942
6072
|
function scan3() {
|
|
4943
6073
|
wsWithRows = /* @__PURE__ */ new Set();
|
|
4944
|
-
for (const el of document.querySelectorAll(
|
|
6074
|
+
for (const el of document.querySelectorAll(TASK_SEL3)) {
|
|
4945
6075
|
const key = el.getAttribute("data-task-item-key") || "";
|
|
4946
6076
|
const ws = workspaceOf2(key);
|
|
4947
6077
|
if (!ws) continue;
|
|
@@ -4967,8 +6097,8 @@
|
|
|
4967
6097
|
if (m.type !== "childList") continue;
|
|
4968
6098
|
for (const n of m.removedNodes) {
|
|
4969
6099
|
if (!(n instanceof Element)) continue;
|
|
4970
|
-
if (n.matches(
|
|
4971
|
-
else for (const r of n.querySelectorAll(
|
|
6100
|
+
if (n.matches(TASK_SEL3)) removed.push(n);
|
|
6101
|
+
else for (const r of n.querySelectorAll(TASK_SEL3)) removed.push(r);
|
|
4972
6102
|
}
|
|
4973
6103
|
}
|
|
4974
6104
|
if (!removed.length) return;
|
|
@@ -5151,7 +6281,7 @@
|
|
|
5151
6281
|
var PEEK_EXEMPT_CLASS = "zcodepro-peek-exempt";
|
|
5152
6282
|
var cssAttr = (v) => String(v).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
5153
6283
|
function installPeekHider(ws) {
|
|
5154
|
-
const rowSel3 = `${
|
|
6284
|
+
const rowSel3 = `${TASK_SEL3}[data-task-item-key^="${cssAttr(ws + ":")}"]`;
|
|
5155
6285
|
for (const r of document.querySelectorAll(rowSel3)) r.classList.add(PEEK_EXEMPT_CLASS);
|
|
5156
6286
|
const style = document.createElement("style");
|
|
5157
6287
|
style.textContent = `${rowSel3}:not(.${PEEK_EXEMPT_CLASS}){display:none!important}`;
|
|
@@ -5163,7 +6293,7 @@
|
|
|
5163
6293
|
for (const r of document.querySelectorAll("." + PEEK_EXEMPT_CLASS)) r.classList.remove(PEEK_EXEMPT_CLASS);
|
|
5164
6294
|
}
|
|
5165
6295
|
function waitForRowsGone(ws) {
|
|
5166
|
-
const sel = `${
|
|
6296
|
+
const sel = `${TASK_SEL3}[data-task-item-key^="${cssAttr(ws + ":")}"]:not(.${PEEK_EXEMPT_CLASS})`;
|
|
5167
6297
|
return new Promise((resolve) => {
|
|
5168
6298
|
const t0 = Date.now();
|
|
5169
6299
|
const timer = setInterval(() => {
|
|
@@ -5185,12 +6315,12 @@
|
|
|
5185
6315
|
}
|
|
5186
6316
|
function relevant(muts) {
|
|
5187
6317
|
for (const m of muts) {
|
|
5188
|
-
if (inSel(m.target,
|
|
6318
|
+
if (inSel(m.target, TASK_SEL3) || inSel(m.target, WS_SEL)) return true;
|
|
5189
6319
|
for (const n of m.addedNodes) {
|
|
5190
|
-
if (n instanceof Element && (n.matches(
|
|
6320
|
+
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL) || n.querySelector(TASK_SEL3) || n.querySelector(WS_SEL))) return true;
|
|
5191
6321
|
}
|
|
5192
6322
|
for (const n of m.removedNodes) {
|
|
5193
|
-
if (n instanceof Element && (n.matches(
|
|
6323
|
+
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL) || n.querySelector(TASK_SEL3))) return true;
|
|
5194
6324
|
}
|
|
5195
6325
|
}
|
|
5196
6326
|
return false;
|
|
@@ -5221,27 +6351,27 @@
|
|
|
5221
6351
|
pollConfig2();
|
|
5222
6352
|
}, pollMs2);
|
|
5223
6353
|
}
|
|
5224
|
-
var
|
|
6354
|
+
var scanDebounce4 = 0;
|
|
5225
6355
|
function startWsRunningSpin() {
|
|
5226
|
-
if (
|
|
5227
|
-
|
|
6356
|
+
if (installed5 || typeof document === "undefined") return;
|
|
6357
|
+
installed5 = true;
|
|
5228
6358
|
void refreshConfig2();
|
|
5229
6359
|
pollConfig2();
|
|
5230
6360
|
const observer2 = new MutationObserver((muts) => {
|
|
5231
6361
|
if (!relevant(muts)) return;
|
|
5232
6362
|
handleRemovals(muts);
|
|
5233
|
-
if (!
|
|
5234
|
-
|
|
5235
|
-
|
|
6363
|
+
if (!scanDebounce4) {
|
|
6364
|
+
scanDebounce4 = setTimeout(() => {
|
|
6365
|
+
scanDebounce4 = 0;
|
|
5236
6366
|
scan3();
|
|
5237
|
-
},
|
|
6367
|
+
}, SCAN_DEBOUNCE_MS4);
|
|
5238
6368
|
}
|
|
5239
6369
|
});
|
|
5240
6370
|
observer2.observe(document.body, { childList: true, subtree: true });
|
|
5241
6371
|
scan3();
|
|
5242
6372
|
setInterval(() => {
|
|
5243
6373
|
if (!document.hidden && enabled3) scan3();
|
|
5244
|
-
},
|
|
6374
|
+
}, SCAN_FALLBACK_MS4);
|
|
5245
6375
|
document.addEventListener("visibilitychange", () => {
|
|
5246
6376
|
if (!document.hidden) scan3();
|
|
5247
6377
|
});
|
|
@@ -5405,7 +6535,7 @@
|
|
|
5405
6535
|
// src/inject/features/toolbar-icons.js
|
|
5406
6536
|
var HIDE_CLASS = "zcodepro-tb-hidden";
|
|
5407
6537
|
var SYNC_DEBOUNCE_MS = 150;
|
|
5408
|
-
var
|
|
6538
|
+
var SCAN_FALLBACK_MS5 = 5e3;
|
|
5409
6539
|
var ROW_SEL = "[data-task-item-key]";
|
|
5410
6540
|
var MENU_SEL = '[data-testid="task-new-button"], [data-testid="automations-open"], [data-testid="plugin-store-sidebar-open"], [data-slot="command"], [data-testid="desktop-top-nav-back"]';
|
|
5411
6541
|
var enabled4 = true;
|
|
@@ -5477,6 +6607,7 @@
|
|
|
5477
6607
|
menu.classList.add(HIDE_CLASS);
|
|
5478
6608
|
origs = next;
|
|
5479
6609
|
rowEl?.remove();
|
|
6610
|
+
navRow.classList.add("zcodepro-tb-hidden-native");
|
|
5480
6611
|
const L = t();
|
|
5481
6612
|
const mk = (kind, orig, nameSel, fallback) => h("button", {
|
|
5482
6613
|
type: "button",
|
|
@@ -5502,7 +6633,9 @@
|
|
|
5502
6633
|
const pIcon = iconOf(next.plugin);
|
|
5503
6634
|
if (pIcon) pluginBtn.append(pIcon);
|
|
5504
6635
|
rowEl = h("div", { class: "zcodepro-tb-row" }, newBtn, searchBtn, autoBtn, pluginBtn);
|
|
5505
|
-
navRow.
|
|
6636
|
+
const updBtn = [...navRow.querySelectorAll("button")].find((b) => /bg-(success|emerald)/.test(b.className || ""));
|
|
6637
|
+
if (updBtn) updBtn.before(rowEl);
|
|
6638
|
+
else navRow.append(rowEl);
|
|
5506
6639
|
return true;
|
|
5507
6640
|
}
|
|
5508
6641
|
function sidebarCollapsed() {
|
|
@@ -5532,10 +6665,18 @@
|
|
|
5532
6665
|
if (sidebarCollapsed() || sidebarTooNarrow()) {
|
|
5533
6666
|
if (rowEl) rowEl.style.display = "none";
|
|
5534
6667
|
menu.classList.remove(HIDE_CLASS);
|
|
6668
|
+
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
5535
6669
|
return;
|
|
5536
6670
|
}
|
|
5537
6671
|
const alive = origs && origs.menu === menu && origs.newTask.isConnected && origs.search.isConnected && origs.auto.isConnected && origs.plugin.isConnected && rowEl && rowEl.isConnected;
|
|
5538
|
-
if (!alive && !rebuild())
|
|
6672
|
+
if (!alive && !rebuild()) {
|
|
6673
|
+
if (rowEl) rowEl.style.display = "none";
|
|
6674
|
+
setTimeout(scheduleSync, 400);
|
|
6675
|
+
setTimeout(scheduleSync, 1200);
|
|
6676
|
+
return;
|
|
6677
|
+
}
|
|
6678
|
+
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6679
|
+
if (navRow) navRow.classList.add("zcodepro-tb-hidden-native");
|
|
5539
6680
|
menu.classList.add(HIDE_CLASS);
|
|
5540
6681
|
if (rowEl) rowEl.style.display = "";
|
|
5541
6682
|
syncActive();
|
|
@@ -5571,6 +6712,7 @@
|
|
|
5571
6712
|
rowEl = null;
|
|
5572
6713
|
if (origs) {
|
|
5573
6714
|
origs.menu.classList.remove(HIDE_CLASS);
|
|
6715
|
+
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
5574
6716
|
origs = null;
|
|
5575
6717
|
}
|
|
5576
6718
|
}
|
|
@@ -5591,7 +6733,7 @@
|
|
|
5591
6733
|
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class", "aria-pressed"] });
|
|
5592
6734
|
setInterval(() => {
|
|
5593
6735
|
if (!document.hidden) sync();
|
|
5594
|
-
},
|
|
6736
|
+
}, SCAN_FALLBACK_MS5);
|
|
5595
6737
|
document.addEventListener("visibilitychange", () => {
|
|
5596
6738
|
if (!document.hidden) sync();
|
|
5597
6739
|
});
|
|
@@ -5602,7 +6744,7 @@
|
|
|
5602
6744
|
var HEAD_CLASS = "zcodepro-pin-head";
|
|
5603
6745
|
var STORE_KEY = "zcodepro:pinned-collapsed";
|
|
5604
6746
|
var SYNC_DEBOUNCE_MS2 = 300;
|
|
5605
|
-
var
|
|
6747
|
+
var SCAN_FALLBACK_MS6 = 5e3;
|
|
5606
6748
|
var enabled5 = true;
|
|
5607
6749
|
var syncTimer2 = 0;
|
|
5608
6750
|
function findPinnedHeader() {
|
|
@@ -5721,7 +6863,7 @@
|
|
|
5721
6863
|
}).observe(document.body, { childList: true, subtree: true });
|
|
5722
6864
|
setInterval(() => {
|
|
5723
6865
|
if (!document.hidden) sync2();
|
|
5724
|
-
},
|
|
6866
|
+
}, SCAN_FALLBACK_MS6);
|
|
5725
6867
|
document.addEventListener("visibilitychange", () => {
|
|
5726
6868
|
if (!document.hidden) sync2();
|
|
5727
6869
|
});
|
|
@@ -5736,7 +6878,7 @@
|
|
|
5736
6878
|
if (status.updates.length === 0) return;
|
|
5737
6879
|
const config = await getConfig();
|
|
5738
6880
|
if ((config.features || {}).autoUpdatePlugins === true) {
|
|
5739
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {
|
|
6881
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
5740
6882
|
if (res.ok) showToast(L.pluginsAutoUpdated, "success");
|
|
5741
6883
|
else showToast(L.pluginsUpdateFailed + ": " + (res.error || ""), "error");
|
|
5742
6884
|
return;
|
|
@@ -5758,8 +6900,14 @@
|
|
|
5758
6900
|
// src/inject/index.js
|
|
5759
6901
|
(function zcodeproInject() {
|
|
5760
6902
|
if (typeof window === "undefined") return;
|
|
5761
|
-
if (window.__zcodeproInjected)
|
|
6903
|
+
if (window.__zcodeproInjected) {
|
|
6904
|
+
const boot = window.__ZCODEPRO__ || {};
|
|
6905
|
+
const sameGeneration = window.__zcodeproBootedToken && boot.token && window.__zcodeproBootedToken === boot.token;
|
|
6906
|
+
if (!sameGeneration) location.reload();
|
|
6907
|
+
return;
|
|
6908
|
+
}
|
|
5762
6909
|
window.__zcodeproInjected = true;
|
|
6910
|
+
window.__zcodeproBootedToken = (window.__ZCODEPRO__ || {}).token || "";
|
|
5763
6911
|
try {
|
|
5764
6912
|
startLocaleResolver();
|
|
5765
6913
|
} catch {
|
|
@@ -5796,6 +6944,10 @@
|
|
|
5796
6944
|
startTitleLock();
|
|
5797
6945
|
} catch {
|
|
5798
6946
|
}
|
|
6947
|
+
try {
|
|
6948
|
+
startTitleGen();
|
|
6949
|
+
} catch {
|
|
6950
|
+
}
|
|
5799
6951
|
try {
|
|
5800
6952
|
startImageMenu();
|
|
5801
6953
|
} catch {
|