zcode-pro 0.16.0__py3-none-any.whl
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.
- zcode_pro/__init__.py +3 -0
- zcode_pro/__main__.py +4 -0
- zcode_pro/app/cli.mjs +9 -0
- zcode_pro/app/dist/inject.js +5821 -0
- zcode_pro/app/src/host/cdp.mjs +126 -0
- zcode_pro/app/src/host/helper.mjs +2134 -0
- zcode_pro/app/src/host/main.mjs +262 -0
- zcode_pro/app/src/host/paths.mjs +73 -0
- zcode_pro/app/src/host/pickFolder.mjs +152 -0
- zcode_pro/app/src/host/settings.mjs +61 -0
- zcode_pro/app/src/host/taskIndex.mjs +255 -0
- zcode_pro/app/src/host/taskOrder.mjs +117 -0
- zcode_pro/app/src/host/webdav.mjs +105 -0
- zcode_pro/app/src/inject/core.js +751 -0
- zcode_pro/app/src/inject/features/alias.js +211 -0
- zcode_pro/app/src/inject/features/copy-path.js +78 -0
- zcode_pro/app/src/inject/features/file-menu.js +147 -0
- zcode_pro/app/src/inject/features/idle-reclaim.js +179 -0
- zcode_pro/app/src/inject/features/image-menu.js +215 -0
- zcode_pro/app/src/inject/features/open-folder.js +43 -0
- zcode_pro/app/src/inject/features/pinned-collapse.js +132 -0
- zcode_pro/app/src/inject/features/pinned-expand.js +142 -0
- zcode_pro/app/src/inject/features/plugin-updates.js +28 -0
- zcode_pro/app/src/inject/features/project-menu.js +58 -0
- zcode_pro/app/src/inject/features/relocate-dialog.js +156 -0
- zcode_pro/app/src/inject/features/session-switch.js +244 -0
- zcode_pro/app/src/inject/features/settings-dialog.js +1503 -0
- zcode_pro/app/src/inject/features/settings-entry.js +21 -0
- zcode_pro/app/src/inject/features/styles.js +311 -0
- zcode_pro/app/src/inject/features/task-order.js +78 -0
- zcode_pro/app/src/inject/features/title-lock.js +242 -0
- zcode_pro/app/src/inject/features/toolbar-icons.js +243 -0
- zcode_pro/app/src/inject/features/ws-running.js +472 -0
- zcode_pro/app/src/inject/index.js +55 -0
- zcode_pro/app/src/inject/ui.js +734 -0
- zcode_pro/cli.py +71 -0
- zcode_pro-0.16.0.dist-info/METADATA +45 -0
- zcode_pro-0.16.0.dist-info/RECORD +41 -0
- zcode_pro-0.16.0.dist-info/WHEEL +4 -0
- zcode_pro-0.16.0.dist-info/entry_points.txt +2 -0
- zcode_pro-0.16.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
// 注入脚本公共工具:与 helper 通信、DOM 构建、多语言文案。
|
|
2
|
+
export const BOOT = typeof window !== 'undefined' ? (window.__ZCODEPRO__ || {}) : {};
|
|
3
|
+
export const HELPER_URL = BOOT.helperUrl || 'http://127.0.0.1:47889';
|
|
4
|
+
const TOKEN = BOOT.token || '';
|
|
5
|
+
|
|
6
|
+
export function rpc(path, options = {}) {
|
|
7
|
+
return fetch(HELPER_URL + path, {
|
|
8
|
+
method: options.method || 'GET',
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': 'application/json',
|
|
11
|
+
'X-ZCodePro-Token': TOKEN,
|
|
12
|
+
},
|
|
13
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
14
|
+
})
|
|
15
|
+
.then((r) => r.json())
|
|
16
|
+
.catch((err) => ({ ok: false, error: String(err && err.message || err) }));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 配置缓存:菜单每次打开时拉取,保证设置弹窗里的开关即时生效
|
|
20
|
+
let configCache = { value: null, at: 0 };
|
|
21
|
+
export async function getConfig(force = false) {
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
if (!force && configCache.value && now - configCache.at < 3000) return configCache.value;
|
|
24
|
+
const res = await rpc('/config');
|
|
25
|
+
if (res.ok && res.config) {
|
|
26
|
+
configCache = { value: res.config, at: now };
|
|
27
|
+
return res.config;
|
|
28
|
+
}
|
|
29
|
+
return configCache.value || { features: {} };
|
|
30
|
+
}
|
|
31
|
+
export function clearConfigCache() { configCache = { value: null, at: 0 }; }
|
|
32
|
+
|
|
33
|
+
const zh = {
|
|
34
|
+
settingsTitle: 'ZCode Pro',
|
|
35
|
+
tabFeatures: '功能',
|
|
36
|
+
tabStyles: '样式',
|
|
37
|
+
tabProxy: '代理',
|
|
38
|
+
tabAgents: '全局提示词',
|
|
39
|
+
agentsDesc: '写入 ~/.zcode/AGENTS.md,作为默认指令用于所有项目的每次会话;保存后从新会话起生效,项目内的 AGENTS.md 可补充或覆盖。内容超过 100KB 会被应用截断。',
|
|
40
|
+
agentsPlaceholder: '填写希望所有项目默认遵循的指令;清空并保存即移除全局提示词',
|
|
41
|
+
agentsSave: '保存',
|
|
42
|
+
agentsSaved: '全局提示词已保存',
|
|
43
|
+
agentsLoadFailed: '读取全局提示词失败',
|
|
44
|
+
proxyDesc: '为 ZCode Pro 本地助手发起的网络访问设置 HTTP 代理:插件市场的更新与安装、Headroom 本体的检查更新与升级都会走该代理。不影响 ZCode 应用本身与模型请求,保存后立即生效。',
|
|
45
|
+
proxyPlaceholder: 'http://127.0.0.1:7890',
|
|
46
|
+
proxySave: '保存',
|
|
47
|
+
proxySaved: '代理设置已保存',
|
|
48
|
+
proxyHint: '留空保存即清除代理。',
|
|
49
|
+
proxyTest: '检测',
|
|
50
|
+
proxyTesting: '检测中…',
|
|
51
|
+
proxyTestFailed: '检测失败',
|
|
52
|
+
tabSync: '同步',
|
|
53
|
+
syncDesc: '手动把 ZCode Pro 设置与模型设置备份到 WebDAV,或在新电脑上恢复。两项各自独立成文件,可只上传或只覆盖其中一项;仅在点击按钮时传输,不做自动同步。',
|
|
54
|
+
syncUrlPlaceholder: 'https://dav.jianguoyun.com/dav/',
|
|
55
|
+
syncDir: '上传目录',
|
|
56
|
+
syncDirPlaceholder: 'zcode-pro',
|
|
57
|
+
syncLogin: '登录',
|
|
58
|
+
syncPassword: '密码',
|
|
59
|
+
syncSave: '保存',
|
|
60
|
+
syncSaved: '同步配置已保存',
|
|
61
|
+
syncFormHint: '同步文件存到“上传目录”(默认 zcode-pro,可多级,自动创建)下的 zcodepro.json 与 model.json。',
|
|
62
|
+
syncRecLink: '坚果云 WebDAV',
|
|
63
|
+
syncRecSuffix: ':登录与密码填“应用密码”,不是账号密码。',
|
|
64
|
+
syncIncludeZcp: 'ZCode Pro 设置',
|
|
65
|
+
syncIncludeZcpDesc: '功能开关、样式调整、项目别名与代理设置;同步配置与凭据本身不参与同步。',
|
|
66
|
+
syncIncludeModel: '模型设置',
|
|
67
|
+
syncIncludeModelDesc: '自定义供应商与模型配置(config.json 与 provider_config.json,含 API Key)。账号登录的凭据(如 BigModel 订阅)不参与同步,各机器用各自账号登录。',
|
|
68
|
+
syncUpload: '上传到云端',
|
|
69
|
+
syncDownload: '从云端下载',
|
|
70
|
+
syncUploading: '上传中…',
|
|
71
|
+
syncDownloading: '下载中…',
|
|
72
|
+
syncUploaded: '已上传到云端',
|
|
73
|
+
syncDownloaded: '已从云端恢复',
|
|
74
|
+
syncLastPush: '上次上传',
|
|
75
|
+
syncLastPull: '上次下载',
|
|
76
|
+
syncNever: '无',
|
|
77
|
+
syncConfirmTitle: '从云端下载',
|
|
78
|
+
syncConfirmDesc: '将用云端数据覆盖本机勾选的同步内容(覆盖前会在原文件旁留下 .zcodepro-backup 备份);本机的同步配置与登录凭据不受影响。模型设置恢复后建议重启 ZCode 生效。确认下载?',
|
|
79
|
+
syncConfirmGo: '确认下载',
|
|
80
|
+
syncHint: '同步登录凭据仅保存在本机 zcodepro.json;模型设置包含自定义供应商的 API Key,只会上传到你自己的 WebDAV。',
|
|
81
|
+
rowGapName: '段落间距',
|
|
82
|
+
rowGapDesc: '会话中段落等文本块之间的垂直间距(回合之间、答案内部)。',
|
|
83
|
+
listSpacingName: '列表上下边距',
|
|
84
|
+
listSpacingDesc: '答案中列表上下的留白。',
|
|
85
|
+
listItemSpacingName: '列表项间距',
|
|
86
|
+
listItemSpacingDesc: '列表中相邻列表项之间的间距。',
|
|
87
|
+
quoteCodeSpacingName: '引用块上下边距',
|
|
88
|
+
quoteCodeSpacingDesc: '引用块与代码块上下的留白。',
|
|
89
|
+
codeLineHeightName: '代码块行高',
|
|
90
|
+
codeLineHeightDesc: '代码块内代码行的行高(倍数)。',
|
|
91
|
+
tableSpacingName: '表格上下边距',
|
|
92
|
+
tableSpacingDesc: '表格上下的留白。',
|
|
93
|
+
tableCellPaddingName: '单元格上下/左右边距',
|
|
94
|
+
tableCellPaddingDesc: '表格单元格内的留白;左输入框为上下、右为左右。',
|
|
95
|
+
lineHeightName: '回答行高',
|
|
96
|
+
lineHeightDesc: '回答正文的行高(倍数)。',
|
|
97
|
+
userLineHeightName: '提问行高',
|
|
98
|
+
userLineHeightDesc: '提问内容的行高(倍数)。',
|
|
99
|
+
contentWidthName: '内容宽度',
|
|
100
|
+
contentWidthDesc: '会话内容的最大宽度,可输入 px 或 %(如 900px、85%);默认显示当前实际宽度,% 相对会话区域。',
|
|
101
|
+
defaultValue: '默认',
|
|
102
|
+
resetDefault: '恢复默认',
|
|
103
|
+
featureProjectMenu: '项目菜单增强',
|
|
104
|
+
featureProjectMenuDesc: '项目“更多”菜单中的自定义别名、切换文件夹、打开文件夹与复制路径(别名同时作用于侧边栏显示)。',
|
|
105
|
+
featureTaskOrder: '侧边栏会话拖动排序',
|
|
106
|
+
featureTaskOrderDesc: '让置顶、项目与分组中的会话拖动后记住顺序,刷新后保持。',
|
|
107
|
+
featureSessionSwitch: '会话快捷切换',
|
|
108
|
+
featureSessionSwitchDesc: 'alt+z 在当前与上次会话间来回切换;按住 alt 再按 x/c 弹出最近会话列表前后选择,松开 alt 切换(类 alt+tab)。',
|
|
109
|
+
featureTitleLock: '重命名会话名锁定',
|
|
110
|
+
featureTitleLockDesc: '手动重命名过的会话不再被自动标题覆盖:会话有新回答后界面可能改显自动标题,重启后又变回,本功能让侧栏始终显示重命名后的名字。',
|
|
111
|
+
featureWsRunning: '折叠项目运行提示(实验性)',
|
|
112
|
+
featureWsRunningDesc: '折叠的项目里仍有会话在运行时,项目图标旋转提示;全部结束或展开项目后恢复。期间每 60 秒在后台短暂展开该项目复核运行状态再收起,会话行不显示,仅项目位置可能有约四分之一秒的轻微高度起伏。',
|
|
113
|
+
tabPerformance: '性能',
|
|
114
|
+
perfDesc: 'ZCode 为每个打开过的项目常驻一个会话进程,应用自身不会回收,项目多了内存占用就高。开启后,长时间未使用且没有任务在跑的项目会被自动释放:会话记录不受影响,再次打开时自动恢复,仅首次回复有几秒等待。正在使用的项目、运行中的会话与后台命令、定时任务都不会被回收。后台命令检测依赖系统进程信息(Linux / macOS / Windows 各走系统自带工具),检测不可用时功能自动停用。',
|
|
115
|
+
featureIdleReclaim: '空闲项目内存回收',
|
|
116
|
+
featureIdleReclaimDesc: '满足条件的项目自动释放内存,会话不受影响,再次打开自动恢复。',
|
|
117
|
+
idleReclaimMinutesLabel: '空闲多久后回收(分钟)',
|
|
118
|
+
idleReclaimStartupLabel: '启动后多久回收一次(分钟)',
|
|
119
|
+
idleReclaimStartupHint: '应用启动会为每个恢复的项目预热进程,到点把未使用的项目一次收掉;0 = 启动后立即回收,该次不受上一项空闲时长限制',
|
|
120
|
+
idleReclaimUnit: '分钟',
|
|
121
|
+
featureToolbarIcons: '侧栏菜单并入顶栏',
|
|
122
|
+
featureToolbarIconsDesc: '把侧边栏顶部的“新建任务 / 搜索 / 自动化 / 插件市场”收成顶部导航栏(后退/前进旁)的图标按钮:悬停显示名称,对应界面打开时高亮,快捷键照常可用;侧边栏原菜单隐藏。',
|
|
123
|
+
tbNewTask: '新建任务',
|
|
124
|
+
tbSearch: '搜索',
|
|
125
|
+
tbAutomations: '自动化',
|
|
126
|
+
tbPluginStore: '插件市场',
|
|
127
|
+
featurePinnedCollapse: '已置顶分区可折叠',
|
|
128
|
+
featurePinnedCollapseDesc: '侧边栏“已置顶”标题可点击折叠/展开其任务列表(与“项目”“分组”分区一致),状态记住。',
|
|
129
|
+
pinnedToggleAria: '折叠/展开已置顶',
|
|
130
|
+
sidebarProjectSpacingName: '项目间距',
|
|
131
|
+
sidebarProjectSpacingDesc: '侧边栏中相邻项目行之间的视觉间距(含行内留白);设置后各分区(已置顶/项目/任务)之间的间距也统一为该值。',
|
|
132
|
+
sidebarTaskSpacingName: '任务间距',
|
|
133
|
+
sidebarTaskSpacingDesc: '侧边栏中相邻任务行之间的垂直间距(含行内上下留白)。',
|
|
134
|
+
uiFontName: '界面字体',
|
|
135
|
+
uiFontDesc: '除终端外所有界面文字的字体(终端字体在官方设置中调整)。',
|
|
136
|
+
userFontName: '提问字体',
|
|
137
|
+
userFontDesc: '会话中提问内容的字体;选“默认”时跟随界面字体。',
|
|
138
|
+
assistantFontName: '回答字体',
|
|
139
|
+
assistantFontDesc: '会话中回答正文的字体(代码块仍用等宽字体);选“默认”时跟随界面字体。',
|
|
140
|
+
switcherHint: 'x / c 选择,松开 alt 切换,Esc 取消',
|
|
141
|
+
switcherCurrent: '当前',
|
|
142
|
+
switcherEmpty: '暂无上次会话(切换过会话后可用)',
|
|
143
|
+
switcherFailed: '未能切换到该会话(可能已删除)',
|
|
144
|
+
featureFileActions: '文件菜单增强',
|
|
145
|
+
featureFileActionsDesc: '在会话中文件链接的右键菜单里新增“默认应用打开”与“打开所在目录”。',
|
|
146
|
+
featureImageCopy: '图片右键复制',
|
|
147
|
+
featureImageCopyDesc: '右键会话中的图片或点击放大的预览图,可将图片复制到剪贴板。',
|
|
148
|
+
imageCopy: '复制图片',
|
|
149
|
+
imageCopied: '图片已复制到剪贴板',
|
|
150
|
+
imageCopyFailed: '复制图片失败',
|
|
151
|
+
openFolderItem: '打开文件夹',
|
|
152
|
+
copyPathItem: '复制路径',
|
|
153
|
+
pathCopied: '路径已复制到剪贴板',
|
|
154
|
+
pathCopyFailed: '复制路径失败',
|
|
155
|
+
fileOpenDefault: '默认应用打开',
|
|
156
|
+
fileReveal: '打开所在目录',
|
|
157
|
+
featurePinnedExpand: '置顶会话保持项目折叠(实验性)',
|
|
158
|
+
featurePinnedExpandDesc: '点击折叠项目的置顶会话后将其保持折叠。受限于应用机制,项目会先短暂展开再缩起。',
|
|
159
|
+
featureAutoUpdatePlugins: '自动更新 zcode-plugins 插件',
|
|
160
|
+
featureAutoUpdatePluginsDesc: '启动时自动检查并更新已装的 zcode-plugins 插件(含安装市场里新增的插件),更新在新会话生效。',
|
|
161
|
+
pluginsUpdateTitle: '插件更新 · zcode-plugins',
|
|
162
|
+
pluginsCheckNow: '检查并更新',
|
|
163
|
+
pluginsUpdating: '正在更新插件…',
|
|
164
|
+
pluginsUpToDate: '插件已是最新',
|
|
165
|
+
pluginsUpdatesFound: '{n} 个插件可更新',
|
|
166
|
+
pluginsUpdatedDone: '已更新 {n} 个插件',
|
|
167
|
+
pluginsUpdateFailed: '插件更新失败',
|
|
168
|
+
pluginsUpdatesAvailable: 'zcode-plugins 有 {n} 个插件可更新(ZCode Pro 设置 → 功能)',
|
|
169
|
+
pluginsAutoUpdated: 'zcode-plugins 插件已更新',
|
|
170
|
+
tabVision: 'Vision',
|
|
171
|
+
visionDesc: '主模型不支持图片输入时(如 glm-5.3),自动把消息里的图片交给下面的视觉模型识别,把描述带给主模型(zcode-vision 插件;/vision-* 命令编辑同一配置)。改动自动保存。',
|
|
172
|
+
visionEnabled: '启用图片识别',
|
|
173
|
+
visionForceIntercept: '主模型能看图也拦截',
|
|
174
|
+
visionMode: '链模式',
|
|
175
|
+
visionModeFallback: '依次尝试',
|
|
176
|
+
visionModeFallbackDesc: '前一个失败才试下一个,任一成功即止(主力 + 备用)。',
|
|
177
|
+
visionModePipeline: '逐级加工',
|
|
178
|
+
visionModePipelineDesc: '每步都执行,后一步加工前一步结果(描述 → 校对/提炼)。',
|
|
179
|
+
visionAddProxy: '添加代理',
|
|
180
|
+
visionRemove: '删除',
|
|
181
|
+
visionMoveUp: '上移',
|
|
182
|
+
visionMoveDown: '下移',
|
|
183
|
+
visionName: '名称',
|
|
184
|
+
visionUseProvider: '供应商',
|
|
185
|
+
visionUseProviderHint: '下拉选择或手动输入:session=跟随当前会话供应商,或供应商名/ID;设置后 baseUrl/API Key/格式自动取该供应商',
|
|
186
|
+
visionUseProviderNone: '不跟随(自填地址)',
|
|
187
|
+
visionUseProviderSession: '跟随当前会话(session)',
|
|
188
|
+
visionUseProviderUnknown: '未找到该供应商,识别时会报错;请从下拉选择,或输入 session',
|
|
189
|
+
visionSkipAfterFailures: '连续失败次数',
|
|
190
|
+
visionSkipAfterFailuresHint: '某代理连续失败满次数后暂时跳过它,直接试下一个;0 = 不跳过',
|
|
191
|
+
visionSkipMinutes: '跳过分钟数',
|
|
192
|
+
visionSkipMinutesHint: '跳过多久后自动恢复尝试;期间任一次成功即清零计数',
|
|
193
|
+
visionResetChain: '恢复默认链',
|
|
194
|
+
visionResetChainConfirm: '将链模式与代理列表恢复为默认两级(glm-session → glm-flash),当前对代理的修改会丢失。继续?',
|
|
195
|
+
visionBaseUrl: '接口地址 baseUrl',
|
|
196
|
+
visionModel: '模型',
|
|
197
|
+
visionFormat: '格式',
|
|
198
|
+
visionApiKey: 'API Key',
|
|
199
|
+
visionApiKeyHint: '留空自动取 GLM 订阅 key',
|
|
200
|
+
visionPrompt: '识别提示词(pipeline 后续步可用 {prev} 引用上一步)',
|
|
201
|
+
visionTest: '测试',
|
|
202
|
+
visionTesting: '测试中…',
|
|
203
|
+
visionTestFailed: '视觉代理测试失败',
|
|
204
|
+
visionTestOutput: '测试输出',
|
|
205
|
+
visionCompressKB: '压缩阈值 KB',
|
|
206
|
+
visionCompressKBHint: '超过该大小的图先压缩再识别(最长边 2000、JPEG);0 = 不压缩',
|
|
207
|
+
visionLoadFailed: '读取视觉代理配置失败',
|
|
208
|
+
tabRtk: 'rtk',
|
|
209
|
+
rtkDesc: 'rtk 插件:把常见开发命令的输出压缩 60-90% 再进入上下文(/rtk-* 命令编辑同一配置)。改动自动保存并立即生效。',
|
|
210
|
+
rtkEnabled: '启用 rtk 压缩',
|
|
211
|
+
rtkNotInstalled: '未安装 rtk,以下配置将在安装后生效(会话里可用 /rtk-setup 安装)',
|
|
212
|
+
rtkWhitelistTitle: '白名单(不压缩直接放行)',
|
|
213
|
+
rtkBuiltinLabel: '内置放行(只读,随插件更新):',
|
|
214
|
+
rtkWhitelistDesc: '每条 name(如 docker)或 git:name(如 git:clone)。输出极小或纯副作用的命令无需压缩,加入后不再压缩;内置的 git add/commit/push、mkdir/cp 等不可移除。删除本文件即恢复默认。',
|
|
215
|
+
rtkWhitelistPlaceholder: 'name 或 git:name,回车添加',
|
|
216
|
+
rtkWhitelistAdd: '添加',
|
|
217
|
+
rtkWhitelistClear: '清空',
|
|
218
|
+
rtkWhitelistCleared: '白名单已清空',
|
|
219
|
+
rtkWhitelistInvalid: '条目格式应为 name 或 git:name',
|
|
220
|
+
rtkLoadFailed: '读取 rtk 配置失败',
|
|
221
|
+
tabHeadroom: 'Headroom',
|
|
222
|
+
headroomDesc: 'Headroom 插件:本地压缩代理驻留 127.0.0.1(默认 8787 端口),压缩发往模型的上下文以省 token(/hr-* 命令编辑同一配置)。压缩设备与省电切换保存后立即生效;切换设备会重启代理,正在处理的请求可能中断一次。',
|
|
223
|
+
headroomBinMissing: '未找到 headroom 程序,代理无法启动;安装 headroom 后以下设置自动生效',
|
|
224
|
+
headroomInstallTitle: '未安装 headroom 插件',
|
|
225
|
+
headroomInstallDesc: '从 zcode-plugins 市场安装后即可在此管理压缩代理;建议安装后重启会话生效。',
|
|
226
|
+
headroomInstall: '安装',
|
|
227
|
+
headroomInstalling: '安装中…',
|
|
228
|
+
headroomInstalled: '已安装 headroom 插件',
|
|
229
|
+
headroomInstallRetry: '安装未生效,请重试或手动在插件市场安装',
|
|
230
|
+
headroomLoadFailed: '读取 Headroom 配置失败',
|
|
231
|
+
headroomStatusTitle: '运行状态',
|
|
232
|
+
headroomStatusLoadFailed: '读取运行状态失败',
|
|
233
|
+
headroomProxyUp: '代理运行中',
|
|
234
|
+
headroomProxyDown: '代理未运行',
|
|
235
|
+
headroomCurrentBackend: '当前设备',
|
|
236
|
+
headroomDesiredBackend: '目标设备',
|
|
237
|
+
hrValAuto: '自动',
|
|
238
|
+
hrPmAc: '交流电',
|
|
239
|
+
hrPmBattery: '电池',
|
|
240
|
+
hrPmSaver: '省电模式',
|
|
241
|
+
hrPmSaverBat: '省电模式+电池',
|
|
242
|
+
hrDetectOk: '正常',
|
|
243
|
+
hrDetectMissing: '未安装',
|
|
244
|
+
hrDetectBroken: '不可用',
|
|
245
|
+
headroomPowerState: '电源',
|
|
246
|
+
headroomWatcher: '监视器',
|
|
247
|
+
headroomWatcherOn: '运行中',
|
|
248
|
+
headroomWatcherOff: '已停止',
|
|
249
|
+
headroomSaverDetect: '省电模式检测',
|
|
250
|
+
headroomRefresh: '刷新',
|
|
251
|
+
headroomStart: '启动',
|
|
252
|
+
headroomRestart: '重启',
|
|
253
|
+
headroomStopAction: '停止',
|
|
254
|
+
headroomStopTitle: '停止 Headroom 代理',
|
|
255
|
+
headroomStopDesc: '停止后,ZCode 中指向该代理(127.0.0.1)的供应商将无法连接,直至重新启动代理。确认停止?',
|
|
256
|
+
headroomStoppedWarn: '代理已停止;指向 127.0.0.1 的供应商将无法连接',
|
|
257
|
+
headroomBackend: '压缩设备',
|
|
258
|
+
headroomBackendAuto: '自动 · 显卡优先',
|
|
259
|
+
headroomBackendCpu: 'CPU · 省电',
|
|
260
|
+
headroomBackendNative: '(原生值)',
|
|
261
|
+
headroomBackendDesc: '自动:headroom 选最快设备(CUDA/MPS 显卡优先);CPU:强制 CPU 压缩,省电且不占显存。也支持 headroom 原生值(onnx、pytorch_mps 等)。切换会重启代理立即生效。',
|
|
262
|
+
headroomPower: '省电自动切换',
|
|
263
|
+
headroomPowerOff: '关闭',
|
|
264
|
+
headroomPowerOffDesc: '不自动切换,始终按“压缩设备”运行。',
|
|
265
|
+
headroomPowerBattery: '用电池时',
|
|
266
|
+
headroomPowerBatteryDesc: '拔电(电池放电)→ CPU 压缩,插电自动切回。',
|
|
267
|
+
headroomPowerSaver: '省电模式时',
|
|
268
|
+
headroomPowerSaverDesc: '仅系统进入省电模式 → CPU 压缩,退出切回。',
|
|
269
|
+
hrCpuPinnedHint: '压缩设备已固定为 CPU,省电自动切换不会再改变它。',
|
|
270
|
+
headroomInterval: '监视间隔',
|
|
271
|
+
headroomIntervalDesc: '省电监视器轮询电源状态的间隔(10–3600 秒,默认 60);保存后从下一轮巡检起生效,无需重启。',
|
|
272
|
+
headroomSecUnit: '秒',
|
|
273
|
+
headroomVersionPlugin: '插件',
|
|
274
|
+
headroomVersionBin: '程序',
|
|
275
|
+
upgradeCheck: '检查更新',
|
|
276
|
+
upgradeChecking: '检查中…',
|
|
277
|
+
upgradeUpToDate: '已是最新({v})',
|
|
278
|
+
upgradeFound: '可升级到 {v}',
|
|
279
|
+
upgradeNow: '升级',
|
|
280
|
+
upgradeRunning: '升级中…',
|
|
281
|
+
upgradeStop: '停止升级',
|
|
282
|
+
upgradeStopped: '已停止升级',
|
|
283
|
+
upgradeDone: '已更新到 {v}',
|
|
284
|
+
upgradeFinished: '升级完成',
|
|
285
|
+
upgradeCheckFailed: '检查更新失败',
|
|
286
|
+
version: '版本',
|
|
287
|
+
close: '关闭',
|
|
288
|
+
cancel: '取消',
|
|
289
|
+
pathLabel: '路径',
|
|
290
|
+
aliasItem: '自定义别名',
|
|
291
|
+
aliasTitle: '自定义项目别名',
|
|
292
|
+
aliasDesc: '仅在 ZCode 界面中显示该别名,不修改磁盘目录与任何数据,随时可清除恢复。',
|
|
293
|
+
aliasLabel: '别名',
|
|
294
|
+
aliasPlaceholder: '留空并保存 = 恢复真实名称',
|
|
295
|
+
aliasConfirm: '保存',
|
|
296
|
+
aliasClear: '恢复真实名称',
|
|
297
|
+
aliasSaved: '别名已更新',
|
|
298
|
+
aliasCleared: '已恢复真实名称',
|
|
299
|
+
aliasHint: '磁盘目录名不变:终端、文件管理器与其他引用真实路径的界面仍显示原名。',
|
|
300
|
+
taskOrderSaved: '顺序已更新',
|
|
301
|
+
qqGroupTitle: 'QQ 群:428403354',
|
|
302
|
+
qqGroupDesc: '问题反馈与交流',
|
|
303
|
+
wechatGroupTitle: '微信群',
|
|
304
|
+
wechatGroupDesc: '添加微信 {id} 邀请进群',
|
|
305
|
+
wechatIdCopied: '微信号已复制',
|
|
306
|
+
browse: '浏览',
|
|
307
|
+
relocateItem: '切换文件夹',
|
|
308
|
+
relocateTitle: '切换文件夹',
|
|
309
|
+
relocateDesc: '将该项目指向另一个文件夹:侧边栏、已打开标签页与本地任务历史一并迁移,目录本身不会被移动,会话记录不会丢失。',
|
|
310
|
+
relocateNewPathLabel: '新文件夹',
|
|
311
|
+
relocateConfirm: '移动',
|
|
312
|
+
relocateHint: '目标文件夹需已存在,可输入路径或点击“浏览”选择;完成后界面将自动刷新。',
|
|
313
|
+
relocateSuccess: '已切换文件夹,正在刷新界面…',
|
|
314
|
+
relocateIndexSkipped: '已切换文件夹;任务历史未能同步(本机缺少 SQLite 支持),旧任务条目可能仍指向旧路径。',
|
|
315
|
+
relocateSame: '新文件夹与当前文件夹相同',
|
|
316
|
+
relocateNotFound: '目标文件夹不存在',
|
|
317
|
+
relocateProtected: '拒绝指向 ZCode 数据目录内部路径',
|
|
318
|
+
relocateIndexBusy: '任务索引正被 ZCode 占用,请稍后重试。',
|
|
319
|
+
relocateConfirmTitle: '确认切换文件夹',
|
|
320
|
+
relocateConfirmDesc: '切换后将自动刷新页面,聊天输入框中未发送的内容会丢失;会话记录与项目文件不受影响。',
|
|
321
|
+
relocateConfirmGo: '确认切换',
|
|
322
|
+
failed: '操作失败',
|
|
323
|
+
retryHint: '请重试',
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const en = {
|
|
327
|
+
settingsTitle: 'ZCode Pro',
|
|
328
|
+
tabFeatures: 'Features',
|
|
329
|
+
tabStyles: 'Styles',
|
|
330
|
+
tabProxy: 'Proxy',
|
|
331
|
+
tabAgents: 'Global Prompt',
|
|
332
|
+
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.',
|
|
333
|
+
agentsPlaceholder: 'Instructions followed by all projects by default; save empty to remove the global prompt',
|
|
334
|
+
agentsSave: 'Save',
|
|
335
|
+
agentsSaved: 'Global prompt saved.',
|
|
336
|
+
agentsLoadFailed: 'Failed to load the global prompt',
|
|
337
|
+
proxyDesc: 'Set an HTTP proxy for network access made by the local helper: plugin marketplace updates and installs, headroom update checks and upgrades. Does not affect the ZCode app itself or model requests. Applies immediately.',
|
|
338
|
+
proxyPlaceholder: 'http://127.0.0.1:7890',
|
|
339
|
+
proxySave: 'Save',
|
|
340
|
+
proxySaved: 'Proxy settings saved.',
|
|
341
|
+
proxyHint: 'Save empty to clear the proxy.',
|
|
342
|
+
proxyTest: 'Test',
|
|
343
|
+
proxyTesting: 'Testing…',
|
|
344
|
+
proxyTestFailed: 'Test failed',
|
|
345
|
+
tabSync: 'Sync',
|
|
346
|
+
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; data moves only when you click, never automatically.',
|
|
347
|
+
syncUrlPlaceholder: 'https://dav.example.com/dav/',
|
|
348
|
+
syncDir: '上传目录',
|
|
349
|
+
syncDirPlaceholder: 'zcode-pro',
|
|
350
|
+
syncLogin: 'Login',
|
|
351
|
+
syncPassword: 'Password',
|
|
352
|
+
syncSave: 'Save',
|
|
353
|
+
syncSaved: 'Sync settings saved.',
|
|
354
|
+
syncFormHint: 'Sync files go to zcodepro.json and model.json inside the folder (default zcode-pro, multi-level allowed, created automatically).',
|
|
355
|
+
syncRecLink: 'Jianguoyun WebDAV',
|
|
356
|
+
syncRecSuffix: ' — use the app password, not your account password.',
|
|
357
|
+
syncIncludeZcp: 'ZCode Pro settings',
|
|
358
|
+
syncIncludeZcpDesc: 'Feature toggles, style adjustments, project aliases and the proxy setting; the sync config and credentials themselves are never synced.',
|
|
359
|
+
syncIncludeModel: 'Model settings',
|
|
360
|
+
syncIncludeModelDesc: 'Custom providers and model config (config.json and provider_config.json, API keys included). Account sign-in credentials (e.g. the BigModel subscription) are not synced; each computer signs in with its own account.',
|
|
361
|
+
syncUpload: 'Upload',
|
|
362
|
+
syncDownload: 'Download',
|
|
363
|
+
syncUploading: 'Uploading…',
|
|
364
|
+
syncDownloading: 'Downloading…',
|
|
365
|
+
syncUploaded: 'Uploaded to the server.',
|
|
366
|
+
syncDownloaded: 'Restored from the server.',
|
|
367
|
+
syncLastPush: 'Last upload',
|
|
368
|
+
syncLastPull: 'Last download',
|
|
369
|
+
syncNever: 'never',
|
|
370
|
+
syncConfirmTitle: 'Download from the server',
|
|
371
|
+
syncConfirmDesc: 'Cloud data will overwrite the selected sections locally (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. Download now?',
|
|
372
|
+
syncConfirmGo: 'Download',
|
|
373
|
+
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.',
|
|
374
|
+
rowGapName: 'Paragraph spacing',
|
|
375
|
+
rowGapDesc: 'Vertical spacing between text blocks (turns, paragraphs inside answers).',
|
|
376
|
+
listSpacingName: 'List spacing',
|
|
377
|
+
listSpacingDesc: 'Space above and below lists.',
|
|
378
|
+
listItemSpacingName: 'List item spacing',
|
|
379
|
+
listItemSpacingDesc: 'Spacing between adjacent list items.',
|
|
380
|
+
quoteCodeSpacingName: 'Quote block spacing',
|
|
381
|
+
quoteCodeSpacingDesc: 'Space above and below quotes and code blocks.',
|
|
382
|
+
codeLineHeightName: 'Code line height',
|
|
383
|
+
codeLineHeightDesc: 'Line height of lines inside code blocks (multiplier).',
|
|
384
|
+
tableSpacingName: 'Table spacing',
|
|
385
|
+
tableSpacingDesc: 'Space above and below tables.',
|
|
386
|
+
tableCellPaddingName: 'Cell padding (V/H)',
|
|
387
|
+
tableCellPaddingDesc: 'Padding inside table cells; left input is vertical, right is horizontal.',
|
|
388
|
+
lineHeightName: 'Answer line height',
|
|
389
|
+
lineHeightDesc: 'Line height of answer text (multiplier).',
|
|
390
|
+
userLineHeightName: 'Question line height',
|
|
391
|
+
userLineHeightDesc: 'Line height of question text (multiplier).',
|
|
392
|
+
contentWidthName: 'Content width',
|
|
393
|
+
contentWidthDesc: 'Max width of conversation content; accepts px or % (e.g. 900px, 85%).',
|
|
394
|
+
defaultValue: 'default',
|
|
395
|
+
resetDefault: 'Reset to default',
|
|
396
|
+
featureProjectMenu: 'Project menu actions',
|
|
397
|
+
featureProjectMenuDesc: 'Custom alias, switch folder, open folder and copy path in the project "More" menu (the alias also applies to the sidebar).',
|
|
398
|
+
featureTaskOrder: 'Sidebar session drag ordering',
|
|
399
|
+
featureTaskOrderDesc: 'Makes session drags in Pinned, Projects and Groups persist across refreshes.',
|
|
400
|
+
featureSessionSwitch: 'Session quick switch',
|
|
401
|
+
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).',
|
|
402
|
+
featureTitleLock: 'Keep renamed session titles',
|
|
403
|
+
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.',
|
|
404
|
+
featureWsRunning: 'Running indicator on collapsed projects (experimental)',
|
|
405
|
+
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 — rows stay hidden, with only a subtle quarter-second height ripple at the project.',
|
|
406
|
+
tabPerformance: 'Performance',
|
|
407
|
+
perfDesc: 'ZCode keeps a session process resident for every project you have opened and never reclaims it, so memory grows with projects. When enabled, projects unused for a while with nothing running release their memory automatically: sessions are untouched and reload when reopened, with a few seconds wait on the first reply. The project in use, running sessions, background commands and scheduled tasks are never reclaimed. Background-command detection reads system process info via built-in tools (Linux / macOS / Windows); when unavailable, the feature disables itself.',
|
|
408
|
+
featureIdleReclaim: 'Idle project memory reclaim',
|
|
409
|
+
featureIdleReclaimDesc: 'Qualifying projects release their memory; sessions are untouched and reload when reopened.',
|
|
410
|
+
idleReclaimMinutesLabel: 'Idle minutes before reclaim',
|
|
411
|
+
idleReclaimStartupLabel: 'Minutes after startup for a one-shot reclaim',
|
|
412
|
+
idleReclaimStartupHint: 'Startup pre-spawns a process per restored project; this pass collects the unused ones once. 0 = reclaim right after startup, ignoring the idle minutes above',
|
|
413
|
+
idleReclaimUnit: 'min',
|
|
414
|
+
featureToolbarIcons: 'Sidebar menu in the top bar',
|
|
415
|
+
featureToolbarIconsDesc: 'Turns the sidebar menu (New task / Search / Automations / Plugin store) into icon buttons next to the back/forward arrows in the top bar: hover shows the name, the button stays highlighted while its view is open, and shortcuts still work; the original sidebar menu is hidden.',
|
|
416
|
+
tbNewTask: 'New task',
|
|
417
|
+
tbSearch: 'Search',
|
|
418
|
+
tbAutomations: 'Automations',
|
|
419
|
+
tbPluginStore: 'Plugin store',
|
|
420
|
+
featurePinnedCollapse: 'Collapsible Pinned section',
|
|
421
|
+
featurePinnedCollapseDesc: 'The sidebar "Pinned" header collapses/expands its task list (like Projects and Groups); the state is remembered.',
|
|
422
|
+
pinnedToggleAria: 'Collapse/expand Pinned',
|
|
423
|
+
sidebarProjectSpacingName: 'Project spacing',
|
|
424
|
+
sidebarProjectSpacingDesc: 'Visual spacing between adjacent project rows in the sidebar (row padding included); when set, section gaps (Pinned/Projects/Tasks) follow the same value.',
|
|
425
|
+
sidebarTaskSpacingName: 'Task spacing',
|
|
426
|
+
sidebarTaskSpacingDesc: 'Vertical spacing between adjacent task rows in the sidebar (row padding included).',
|
|
427
|
+
uiFontName: 'UI font',
|
|
428
|
+
uiFontDesc: 'Font for all interface text except the terminal (its font is set in the official settings).',
|
|
429
|
+
userFontName: 'Question font',
|
|
430
|
+
userFontDesc: 'Font of question text in conversations; "default" follows the UI font.',
|
|
431
|
+
assistantFontName: 'Answer font',
|
|
432
|
+
assistantFontDesc: 'Font of answer text in conversations (code blocks stay monospaced); "default" follows the UI font.',
|
|
433
|
+
switcherHint: 'x / c to choose, release alt to switch, Esc to cancel',
|
|
434
|
+
switcherCurrent: 'current',
|
|
435
|
+
switcherEmpty: 'No previous session yet (available after you switch sessions)',
|
|
436
|
+
switcherFailed: 'Failed to switch to that session (it may have been deleted)',
|
|
437
|
+
featureFileActions: 'File menu actions',
|
|
438
|
+
featureFileActionsDesc: 'Adds "Open with default app" and "Reveal in file manager" to the right-click menu of file links in chat.',
|
|
439
|
+
featureImageCopy: 'Image right-click copy',
|
|
440
|
+
featureImageCopyDesc: 'Right-click an image in chat or the enlarged preview to copy it to the clipboard.',
|
|
441
|
+
imageCopy: 'Copy image',
|
|
442
|
+
imageCopied: 'Image copied to the clipboard.',
|
|
443
|
+
imageCopyFailed: 'Failed to copy the image.',
|
|
444
|
+
openFolderItem: 'Open folder',
|
|
445
|
+
copyPathItem: 'Copy path',
|
|
446
|
+
pathCopied: 'Path copied to the clipboard.',
|
|
447
|
+
pathCopyFailed: 'Failed to copy the path.',
|
|
448
|
+
fileOpenDefault: 'Open with default app',
|
|
449
|
+
fileReveal: 'Reveal in file manager',
|
|
450
|
+
featurePinnedExpand: 'Keep projects collapsed for pinned sessions (experimental)',
|
|
451
|
+
featurePinnedExpandDesc: 'Keeps the project collapsed after clicking a pinned session. Note: it briefly expands first, then collapses.',
|
|
452
|
+
featureAutoUpdatePlugins: 'Auto-update zcode-plugins plugins',
|
|
453
|
+
featureAutoUpdatePluginsDesc: 'Checks and updates installed zcode-plugins plugins on startup (including newly added ones). Updates apply to new sessions.',
|
|
454
|
+
pluginsUpdateTitle: 'Plugin updates · zcode-plugins',
|
|
455
|
+
pluginsCheckNow: 'Check & update',
|
|
456
|
+
pluginsUpdating: 'Updating plugins…',
|
|
457
|
+
pluginsUpToDate: 'Plugins are up to date',
|
|
458
|
+
pluginsUpdatesFound: '{n} plugin(s) can be updated',
|
|
459
|
+
pluginsUpdatedDone: 'Updated {n} plugin(s)',
|
|
460
|
+
pluginsUpdateFailed: 'Plugin update failed',
|
|
461
|
+
pluginsUpdatesAvailable: '{n} zcode-plugins update(s) available (ZCode Pro settings → Features)',
|
|
462
|
+
pluginsAutoUpdated: 'zcode-plugins updated',
|
|
463
|
+
tabVision: 'Vision',
|
|
464
|
+
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.',
|
|
465
|
+
visionEnabled: 'Enable image recognition',
|
|
466
|
+
visionForceIntercept: 'Intercept even if the main model sees images',
|
|
467
|
+
visionMode: 'Chain mode',
|
|
468
|
+
visionModeFallback: 'Fallback',
|
|
469
|
+
visionModeFallbackDesc: 'Try in order until one succeeds (primary + backup).',
|
|
470
|
+
visionModePipeline: 'Pipeline',
|
|
471
|
+
visionModePipelineDesc: 'Every step runs; later steps refine earlier results (describe → refine).',
|
|
472
|
+
visionAddProxy: 'Add proxy',
|
|
473
|
+
visionRemove: 'Remove',
|
|
474
|
+
visionMoveUp: 'Up',
|
|
475
|
+
visionMoveDown: 'Down',
|
|
476
|
+
visionName: 'Name',
|
|
477
|
+
visionUseProvider: 'Provider',
|
|
478
|
+
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',
|
|
479
|
+
visionUseProviderNone: 'Not following (enter base URL)',
|
|
480
|
+
visionUseProviderSession: 'Follow session provider (session)',
|
|
481
|
+
visionUseProviderUnknown: 'Unknown provider; recognition will fail. Pick from the list or type session',
|
|
482
|
+
visionSkipAfterFailures: 'Skip after failures',
|
|
483
|
+
visionSkipAfterFailuresHint: 'After this many consecutive failures a proxy is skipped and the next one is tried; 0 = never skip',
|
|
484
|
+
visionSkipMinutes: 'Skip minutes',
|
|
485
|
+
visionSkipMinutesHint: 'How long a skipped proxy rests before being retried; any success resets the counter',
|
|
486
|
+
visionResetChain: 'Reset default chain',
|
|
487
|
+
visionResetChainConfirm: 'Reset chain mode and the proxy list to the default 2-level chain (glm-session → glm-flash)? Current proxy edits will be lost. Continue?',
|
|
488
|
+
visionBaseUrl: 'Base URL',
|
|
489
|
+
visionModel: 'Model',
|
|
490
|
+
visionFormat: 'Format',
|
|
491
|
+
visionApiKey: 'API Key',
|
|
492
|
+
visionApiKeyHint: 'Leave empty to reuse the GLM subscription key',
|
|
493
|
+
visionPrompt: 'Recognition prompt ({prev} = previous step in pipeline)',
|
|
494
|
+
visionTest: 'Test',
|
|
495
|
+
visionTesting: 'Testing…',
|
|
496
|
+
visionTestFailed: 'Vision proxy test failed',
|
|
497
|
+
visionTestOutput: 'Test output',
|
|
498
|
+
visionCompressKB: 'Compress threshold KB',
|
|
499
|
+
visionCompressKBHint: 'Images above this size are compressed first (max edge 2000, JPEG); 0 = never',
|
|
500
|
+
visionLoadFailed: 'Failed to load the vision config',
|
|
501
|
+
tabRtk: 'rtk',
|
|
502
|
+
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.',
|
|
503
|
+
rtkEnabled: 'Enable rtk compression',
|
|
504
|
+
rtkNotInstalled: 'rtk is not installed. The settings below take effect after installation (/rtk-setup in a session).',
|
|
505
|
+
rtkWhitelistTitle: 'Whitelist (pass through without compression)',
|
|
506
|
+
rtkBuiltinLabel: 'Built-in exemptions (read-only, follow plugin updates):',
|
|
507
|
+
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, …) cannot be removed. Delete the file to reset.',
|
|
508
|
+
rtkWhitelistPlaceholder: 'name or git:name, press Enter to add',
|
|
509
|
+
rtkWhitelistAdd: 'Add',
|
|
510
|
+
rtkWhitelistClear: 'Clear',
|
|
511
|
+
rtkWhitelistCleared: 'Whitelist cleared',
|
|
512
|
+
rtkWhitelistInvalid: 'Entry must be name or git:name',
|
|
513
|
+
rtkLoadFailed: 'Failed to load the rtk config',
|
|
514
|
+
tabHeadroom: 'Headroom',
|
|
515
|
+
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.',
|
|
516
|
+
headroomBinMissing: 'The headroom program was not found, so the proxy cannot start. The settings below take effect once it is installed.',
|
|
517
|
+
headroomInstallTitle: 'headroom plugin not installed',
|
|
518
|
+
headroomInstallDesc: 'Install it from the zcode-plugins marketplace to manage the compression proxy here; restarting the session afterwards is recommended.',
|
|
519
|
+
headroomInstall: 'Install',
|
|
520
|
+
headroomInstalling: 'Installing…',
|
|
521
|
+
headroomInstalled: 'headroom plugin installed',
|
|
522
|
+
headroomInstallRetry: 'Installation did not take effect; retry or install it from the marketplace manually',
|
|
523
|
+
headroomLoadFailed: 'Failed to load the Headroom config',
|
|
524
|
+
headroomStatusTitle: 'Status',
|
|
525
|
+
headroomStatusLoadFailed: 'Failed to load the status',
|
|
526
|
+
headroomProxyUp: 'Proxy running',
|
|
527
|
+
headroomProxyDown: 'Proxy down',
|
|
528
|
+
headroomCurrentBackend: 'Current device',
|
|
529
|
+
headroomDesiredBackend: 'Target device',
|
|
530
|
+
hrValAuto: 'Auto',
|
|
531
|
+
hrPmAc: 'AC',
|
|
532
|
+
hrPmBattery: 'Battery',
|
|
533
|
+
hrPmSaver: 'Power saver',
|
|
534
|
+
hrPmSaverBat: 'Saver + battery',
|
|
535
|
+
hrDetectOk: 'OK',
|
|
536
|
+
hrDetectMissing: 'missing',
|
|
537
|
+
hrDetectBroken: 'unavailable',
|
|
538
|
+
headroomPowerState: 'Power',
|
|
539
|
+
headroomWatcher: 'Watcher',
|
|
540
|
+
headroomWatcherOn: 'Running',
|
|
541
|
+
headroomWatcherOff: 'Stopped',
|
|
542
|
+
headroomSaverDetect: 'Power-saver detection',
|
|
543
|
+
headroomRefresh: 'Refresh',
|
|
544
|
+
headroomStart: 'Start',
|
|
545
|
+
headroomRestart: 'Restart',
|
|
546
|
+
headroomStopAction: 'Stop',
|
|
547
|
+
headroomStopTitle: 'Stop the Headroom proxy',
|
|
548
|
+
headroomStopDesc: 'Providers in ZCode that point at this proxy (127.0.0.1) will fail to connect until it is started again. Stop it?',
|
|
549
|
+
headroomStoppedWarn: 'Proxy stopped; providers pointing at 127.0.0.1 cannot connect.',
|
|
550
|
+
headroomBackend: 'Compression device',
|
|
551
|
+
headroomBackendAuto: 'Auto · GPU first',
|
|
552
|
+
headroomBackendCpu: 'CPU · power saving',
|
|
553
|
+
headroomBackendNative: ' (native)',
|
|
554
|
+
headroomBackendDesc: 'Auto lets headroom pick the fastest device (CUDA/MPS); CPU forces CPU compression (power saving, no VRAM). Native headroom values (onnx, pytorch_mps, …) also work. Switching restarts the proxy to apply.',
|
|
555
|
+
headroomPower: 'Power-save auto switch',
|
|
556
|
+
headroomPowerOff: 'Off',
|
|
557
|
+
headroomPowerOffDesc: 'No auto switching; always follow the compression device.',
|
|
558
|
+
headroomPowerBattery: 'On battery',
|
|
559
|
+
headroomPowerBatteryDesc: 'On battery (discharging) → CPU; switches back when plugged in.',
|
|
560
|
+
headroomPowerSaver: 'Power-saver',
|
|
561
|
+
headroomPowerSaverDesc: 'Only the system power-saver mode → CPU; back when it exits.',
|
|
562
|
+
hrCpuPinnedHint: 'The compression device is pinned to CPU, so power-save switching no longer changes anything.',
|
|
563
|
+
headroomInterval: 'Watch interval',
|
|
564
|
+
headroomIntervalDesc: 'Seconds between power checks (10–3600, default 60); applies from the next round, no restart needed.',
|
|
565
|
+
headroomSecUnit: 's',
|
|
566
|
+
headroomVersionPlugin: 'plugin',
|
|
567
|
+
headroomVersionBin: 'program',
|
|
568
|
+
upgradeCheck: 'Check update',
|
|
569
|
+
upgradeChecking: 'Checking…',
|
|
570
|
+
upgradeUpToDate: 'Up to date ({v})',
|
|
571
|
+
upgradeFound: '{v} available',
|
|
572
|
+
upgradeNow: 'Update',
|
|
573
|
+
upgradeRunning: 'Updating…',
|
|
574
|
+
upgradeStop: 'Stop',
|
|
575
|
+
upgradeStopped: 'Upgrade stopped',
|
|
576
|
+
upgradeDone: 'Updated to {v}',
|
|
577
|
+
upgradeFinished: 'Update finished',
|
|
578
|
+
upgradeCheckFailed: 'Update check failed',
|
|
579
|
+
version: 'Version',
|
|
580
|
+
close: 'Close',
|
|
581
|
+
cancel: 'Cancel',
|
|
582
|
+
pathLabel: 'Path',
|
|
583
|
+
aliasItem: 'Custom alias',
|
|
584
|
+
aliasTitle: 'Custom alias',
|
|
585
|
+
aliasDesc: 'Shown in the ZCode UI only. The directory on disk and all data stay untouched; revert anytime.',
|
|
586
|
+
aliasLabel: 'Alias',
|
|
587
|
+
aliasPlaceholder: 'Leave empty and save to restore the real name',
|
|
588
|
+
aliasConfirm: 'Save',
|
|
589
|
+
aliasClear: 'Restore real name',
|
|
590
|
+
aliasSaved: 'Alias updated.',
|
|
591
|
+
aliasCleared: 'Real name restored.',
|
|
592
|
+
aliasHint: 'The directory name on disk is unchanged: terminals, file managers and other path-based UI still show the real name.',
|
|
593
|
+
taskOrderSaved: 'Order updated.',
|
|
594
|
+
qqGroupTitle: 'QQ group: 428403354',
|
|
595
|
+
qqGroupDesc: 'Feedback & discussion',
|
|
596
|
+
wechatGroupTitle: 'WeChat group',
|
|
597
|
+
wechatGroupDesc: 'Add WeChat {id} for a group invite',
|
|
598
|
+
wechatIdCopied: 'WeChat ID copied.',
|
|
599
|
+
browse: 'Browse',
|
|
600
|
+
relocateItem: 'Switch folder',
|
|
601
|
+
relocateTitle: 'Switch folder',
|
|
602
|
+
relocateDesc: 'Points this project at another folder: the sidebar, open tabs and local task history move along. The directory itself is not moved and no sessions are lost.',
|
|
603
|
+
relocateNewPathLabel: 'New folder',
|
|
604
|
+
relocateConfirm: 'Move',
|
|
605
|
+
relocateHint: 'The target folder must already exist. Enter a path or use Browse; the UI refreshes automatically afterwards.',
|
|
606
|
+
relocateSuccess: 'Folder switched. Refreshing…',
|
|
607
|
+
relocateIndexSkipped: 'Folder switched, but the task history was not synced (SQLite support missing); old entries may still point to the old path.',
|
|
608
|
+
relocateSame: 'The new folder is the same as the current one.',
|
|
609
|
+
relocateNotFound: 'The target folder does not exist.',
|
|
610
|
+
relocateProtected: 'Refusing to point inside the ZCode data directory.',
|
|
611
|
+
relocateIndexBusy: 'The task index is busy (ZCode may be writing). Please retry shortly.',
|
|
612
|
+
relocateConfirmTitle: 'Confirm folder switch',
|
|
613
|
+
relocateConfirmDesc: 'The page will refresh after switching, and unsent text in the chat input will be lost. Sessions and project files are not affected.',
|
|
614
|
+
relocateConfirmGo: 'Confirm switch',
|
|
615
|
+
failed: 'Operation failed',
|
|
616
|
+
retryHint: 'Please retry',
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
// 界面语言:与官方 IntlProvider 的解析一致——先读应用的 localStorage 偏好
|
|
620
|
+
// (zcode-locale-preference:zh-CN/en-US/system),'system' 或读取失败时回退 navigator.language
|
|
621
|
+
export function isZhLocale() {
|
|
622
|
+
let pref = null;
|
|
623
|
+
try { pref = window.localStorage.getItem('zcode-locale-preference'); } catch { /* ignore */ }
|
|
624
|
+
if (pref === 'zh-CN' || pref === 'en-US') return pref === 'zh-CN';
|
|
625
|
+
return /^zh/i.test(navigator.language || 'zh-CN');
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
export function t() {
|
|
629
|
+
return isZhLocale() ? zh : en;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// helper 错误消息的英文映射(code → 文案):helper 原文为中文,非中文界面按 code 显示英文,
|
|
633
|
+
// 无映射或中文界面回退 helper 原文
|
|
634
|
+
const errEn = {
|
|
635
|
+
'invalid-path': 'Invalid project path',
|
|
636
|
+
'not-found': 'The folder does not exist',
|
|
637
|
+
'invalid-request': 'Invalid request',
|
|
638
|
+
'invalid-content': 'content must be a string',
|
|
639
|
+
'agents-read': 'Failed to read AGENTS.md',
|
|
640
|
+
'agents-write': 'Failed to write AGENTS.md',
|
|
641
|
+
'config-save': 'Failed to save config',
|
|
642
|
+
'settings-write': 'Failed to update setting.json',
|
|
643
|
+
'workspace-empty': 'Workspace not found or has no sessions',
|
|
644
|
+
'order-write': 'Failed to persist ordering',
|
|
645
|
+
'group-not-found': 'No group contains these sessions',
|
|
646
|
+
'group-ambiguous': 'Cannot determine the group uniquely',
|
|
647
|
+
'name-too-long': 'Alias too long (max 100 characters)',
|
|
648
|
+
'name-invalid-chars': 'Alias must not contain newlines or control characters',
|
|
649
|
+
'index-remap-failed': 'Failed to update the task index (config changes rolled back)',
|
|
650
|
+
'index-error': 'Task index error',
|
|
651
|
+
'index-busy': 'The task index is busy. Please retry shortly.',
|
|
652
|
+
'vision-invalid': 'Invalid vision config',
|
|
653
|
+
'vision-read': 'Failed to read zcode-vision.json',
|
|
654
|
+
'vision-write': 'Failed to write zcode-vision.json',
|
|
655
|
+
'vision-test': 'Vision test failed',
|
|
656
|
+
'proxy-invalid': 'Proxy must look like http://127.0.0.1:7890, or be empty',
|
|
657
|
+
'proxy-not-set': 'Set the proxy address first',
|
|
658
|
+
'rtk-invalid': 'Invalid rtk config',
|
|
659
|
+
'rtk-update': 'Failed to check rtk updates (GitHub Releases unreachable? Set a proxy in the Proxy tab)',
|
|
660
|
+
'rtk-write': 'Failed to write the rtk config',
|
|
661
|
+
'headroom-read': 'Failed to read headroom.json',
|
|
662
|
+
'headroom-write': 'Failed to write headroom.json',
|
|
663
|
+
'headroom-invalid': 'Invalid headroom setting',
|
|
664
|
+
'headroom-plugin': 'headroom plugin not found (install it from the marketplace)',
|
|
665
|
+
'headroom-sh': 'sh not found; cannot run the headroom plugin script',
|
|
666
|
+
'headroom-action': 'The headroom action failed',
|
|
667
|
+
'headroom-status': 'Failed to read the headroom status',
|
|
668
|
+
'headroom-upgrade': 'headroom upgrade failed',
|
|
669
|
+
'plugins-status': 'Failed to read the plugin list',
|
|
670
|
+
'plugins-update': 'Failed to update plugins',
|
|
671
|
+
'sync-invalid': 'Invalid sync settings',
|
|
672
|
+
'sync-not-configured': 'Set the sync type to WebDAV and save the config first',
|
|
673
|
+
'sync-remote-missing': 'No synced data on the server yet; upload from another computer first',
|
|
674
|
+
'sync-remote-invalid': 'The URL already holds a different file; use another file path',
|
|
675
|
+
'sync-request': 'The WebDAV request failed',
|
|
676
|
+
'sync-run': 'Sync failed',
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
export function errText(res) {
|
|
680
|
+
if (!res) return '';
|
|
681
|
+
if (!isZhLocale()) {
|
|
682
|
+
const en = res.code && errEn[res.code];
|
|
683
|
+
if (en) return en;
|
|
684
|
+
}
|
|
685
|
+
return res.error || '';
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
export function h(tag, attrs, ...children) {
|
|
689
|
+
const el = document.createElement(tag);
|
|
690
|
+
if (attrs) {
|
|
691
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
692
|
+
if (k === 'class') el.className = v;
|
|
693
|
+
else if (k === 'style') el.setAttribute('style', v);
|
|
694
|
+
else if (k.startsWith('on') && typeof v === 'function') el.addEventListener(k.slice(2).toLowerCase(), v);
|
|
695
|
+
else if (v === true) el.setAttribute(k, '');
|
|
696
|
+
else if (v !== false && v !== undefined && v !== null) el.setAttribute(k, String(v));
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
for (const c of children.flat(Infinity)) {
|
|
700
|
+
if (c === undefined || c === null || c === false) continue;
|
|
701
|
+
el.append(c.nodeType ? c : document.createTextNode(String(c)));
|
|
702
|
+
}
|
|
703
|
+
return el;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export function closeRadixMenu(contentEl) {
|
|
707
|
+
try {
|
|
708
|
+
contentEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape', bubbles: true, cancelable: true }));
|
|
709
|
+
} catch { /* ignore */ }
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// 观察 Radix 弹层(下拉菜单/弹出框)出现,回调 content 元素
|
|
713
|
+
export function observeRadixPopups(onPopup) {
|
|
714
|
+
const seen = new WeakSet();
|
|
715
|
+
const check = (node) => {
|
|
716
|
+
if (!(node instanceof HTMLElement)) return;
|
|
717
|
+
if (node.hasAttribute('data-radix-popper-content-wrapper')) {
|
|
718
|
+
// wrapper 先出现,content 在下一帧内插入
|
|
719
|
+
requestAnimationFrame(() => {
|
|
720
|
+
const content = node.firstElementChild;
|
|
721
|
+
if (content && !seen.has(content)) {
|
|
722
|
+
seen.add(content);
|
|
723
|
+
onPopup(content);
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
// 兜底:直接观察 role=menu 的 content。延迟一帧再回调——Radix 偶尔分两帧渲染
|
|
728
|
+
// (先挂 menu 容器、下一帧才填菜单项),立即回调时菜单项为空,调用方找不到
|
|
729
|
+
// 锚点项就永远漏注入(菜单项填入不会再产生 role=menu 节点添加事件)
|
|
730
|
+
if (node.getAttribute && node.getAttribute('role') === 'menu' && !seen.has(node)) {
|
|
731
|
+
seen.add(node);
|
|
732
|
+
requestAnimationFrame(() => {
|
|
733
|
+
if (node.isConnected) onPopup(node);
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
const process = (mutations) => {
|
|
738
|
+
for (const m of mutations) for (const n of m.addedNodes) check(n);
|
|
739
|
+
};
|
|
740
|
+
const observer = new MutationObserver(process);
|
|
741
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
742
|
+
return observer;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
export function itemsOf(menuEl) {
|
|
746
|
+
return [...menuEl.querySelectorAll('[role="menuitem"]')];
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
export function itemText(item) {
|
|
750
|
+
return (item.textContent || '').trim();
|
|
751
|
+
}
|