zcode-pro 0.18.0 → 0.20.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.
@@ -43,6 +43,7 @@ const zh = {
43
43
  tabFeatures: '功能',
44
44
  tabStyles: '样式',
45
45
  tabProxy: '代理',
46
+ tabBehavior: '行为',
46
47
  tabAgents: '全局提示词',
47
48
  agentsDesc: '写入 ~/.zcode/AGENTS.md,作为默认指令用于所有项目的每次会话;保存后从新会话起生效,项目内的 AGENTS.md 可补充或覆盖。内容超过 100KB 会被应用截断。',
48
49
  agentsPlaceholder: '填写希望所有项目默认遵循的指令;清空并保存即移除全局提示词',
@@ -66,12 +67,16 @@ const zh = {
66
67
  proxyScopeSyncDesc: 'WebDAV 上传与下载走代理。默认关闭:坚果云等国内网盘直连即可,代理停了同步会跟着失败。',
67
68
  tabSync: '同步',
68
69
  tabDebug: '调试',
69
- syncDesc: '手动把 ZCode Pro 设置与模型设置备份到 WebDAV,或在新电脑上恢复。两项各自独立成文件,可只上传或只覆盖其中一项;每次上传会额外保留一份带时间戳的历史版本,下载时任选一个版本恢复;仅在点击按钮时传输,不做自动同步。',
70
+ syncDesc: '手动把 ZCode Pro 设置与模型设置备份到 WebDAV,或在新电脑上恢复。两项各自独立成文件,可只上传或只覆盖其中一项;每次上传会额外保留一份带时间戳的历史版本(保留多少个见“历史版本”一行,上传后自动删除超出的最旧版本),下载时任选一个版本恢复;仅在点击按钮时传输,不做自动同步。',
70
71
  syncUrlPlaceholder: 'https://dav.jianguoyun.com/dav/',
71
72
  syncDir: '上传目录',
72
73
  syncDirPlaceholder: 'zcode-pro',
73
74
  syncLogin: '登录',
74
75
  syncPassword: '密码',
76
+ syncHistoryLimit: '历史版本',
77
+ syncHistoryLimitUnit: '个',
78
+ syncHistoryLimitHint: '云端最多保留最近几次上传留下的历史版本,上传成功后自动删除更早的;固定名最新版不受影响;0 = 不保留历史版本',
79
+ syncPruned: '已清理 {n} 个更早的历史版本',
75
80
  syncSave: '保存',
76
81
  syncSaved: '同步配置已保存',
77
82
  syncFormHint: '同步文件存到“上传目录”(默认 zcode-pro,可多级,自动创建):zcodepro.json 与 model.json 始终是最新一版,旁边另保留带时间戳的历史版本。',
@@ -92,8 +97,8 @@ const zh = {
92
97
  syncConfirmTitle: '从云端下载',
93
98
  syncConfirmDesc: '将用所选文件覆盖本机对应的一项(覆盖前会在原文件旁留下 .zcodepro-backup 备份);本机的同步配置与登录凭据不受影响。模型设置恢复后建议重启 ZCode 生效。确认导入?',
94
99
  syncConfirmGo: '确认导入',
95
- syncPickDesc: '固定名文件始终是最新一版,带时间戳的是每次上传留下的历史版本;「导入」用所选文件覆盖本机对应的一项。',
96
- syncVerDeleteLatestNote: '注意:这是“最新”文件,旧版 zcode-pro 的「从云端下载」依赖它,删除后旧版机器将无法下载;带时间戳的历史版本不受影响。',
100
+ syncPickDesc: '固定名文件始终是最新一版,带时间戳的是每次上传留下的历史版本;“导入”用所选文件覆盖本机对应的一项。',
101
+ syncVerDeleteLatestNote: '注意:这是“最新”文件,旧版 zcode-pro 的“从云端下载”依赖它,删除后旧版机器将无法下载;带时间戳的历史版本不受影响。',
97
102
  syncHint: '同步登录凭据仅保存在本机 zcodepro.json;模型设置包含自定义供应商的 API Key,只会上传到你自己的 WebDAV。',
98
103
  syncTest: '测试',
99
104
  syncTesting: '测试中…',
@@ -117,8 +122,8 @@ const zh = {
117
122
  syncVerDeleted: '已删除云端备份',
118
123
  syncVerSaved: '已保存到',
119
124
  devMode: '开发模式',
120
- devModeRowDesc: '开启后出现「重载 ZCode Pro」按钮;也可给启动器设环境变量 ZCODEPRO_DEV=1 启用。此标签页仅在开发模式生效时显示。',
121
- devModeDesc: '开发调试用:改完 zcode-pro 代码后不必重启 ZCode,点「重载 ZCode Pro」即可加载新代码。流程为自动构建(需在源码目录运行)→ 以新进程重启 ZCode Pro(本地助手与注入脚本都换新)→ 所有 ZCode 窗口自动刷新并重新注入;ZCode 本体与已打开的会话不受影响。',
125
+ devModeRowDesc: '开启后出现“重载 ZCode Pro”按钮;也可给启动器设环境变量 ZCODEPRO_DEV=1 启用。此标签页仅在开发模式生效时显示。',
126
+ devModeDesc: '开发调试用:改完 zcode-pro 代码后不必重启 ZCode,点“重载 ZCode Pro”即可加载新代码。流程为自动构建(需在源码目录运行)→ 以新进程重启 ZCode Pro(本地助手与注入脚本都换新)→ 所有 ZCode 窗口自动刷新并重新注入;ZCode 本体与已打开的会话不受影响。',
122
127
  devReload: '重载 ZCode Pro',
123
128
  devReloading: '重载中…',
124
129
  devReloadDesc: '点击后约 2-3 秒内所有 ZCode 窗口自动刷新一次并加载新脚本。',
@@ -139,7 +144,7 @@ const zh = {
139
144
  lineHeightName: '回答行高',
140
145
  lineHeightDesc: '回答正文的行高(倍数)。',
141
146
  thinkingLineHeightName: '思考行高',
142
- thinkingLineHeightDesc: '「已工作/工作中」过程记录(读取/编辑/查阅/终端条目与思考内容)的行高(倍数)。',
147
+ thinkingLineHeightDesc: '“已工作/工作中”过程记录(读取/编辑/查阅/终端条目与思考内容)的行高(倍数)。',
143
148
  userLineHeightName: '提问行高',
144
149
  userLineHeightDesc: '提问内容的行高(倍数)。',
145
150
  contentWidthName: '内容宽度',
@@ -154,6 +159,30 @@ const zh = {
154
159
  featureSessionSwitchDesc: 'alt+z 在当前与上次会话间来回切换;按住 alt 再按 x/c 弹出最近会话列表前后选择,松开 alt 切换(类 alt+tab)。',
155
160
  featureTitleLock: '重命名会话名锁定',
156
161
  featureTitleLockDesc: '手动重命名过的会话不再被自动标题覆盖:会话有新回答后界面可能改显自动标题,重启后又变回,本功能让侧栏始终显示重命名后的名字。',
162
+ tabTitleGen: '任务名提示词',
163
+ titleGenShortDesc: '新会话开始作答时,按所选供应商与提示词生成任务名并按手动重命名保存,官方自动标题不再覆盖。',
164
+ titleGenEnabled: '启用',
165
+ titleGenProvider: '供应商',
166
+ titleGenProviderNone: '不跟随(自填地址)',
167
+ titleGenProviderSession: '跟随当前会话',
168
+ titleGenProviderDeleted: '(已删除)',
169
+ titleGenModel: '模型',
170
+ titleGenModelHint: '从列表选择,或直接填写模型 id',
171
+ titleGenModelEmpty: '(未选择)',
172
+ titleGenModelSessionHint: '从列表选择模型;列表第一项为跟随会话当前模型',
173
+ titleGenModelFollowSession: '跟随当前会话当前模型',
174
+ titleGenModelManualHint: '输入模型 id',
175
+ titleGenBaseUrl: '接口地址',
176
+ titleGenApiKey: 'API Key',
177
+ titleGenFormat: '协议',
178
+ titleGenPrompt: '提示词',
179
+ titleGenPromptPlaceholder: '留空使用内置默认提示词(点击下方按钮可查看)',
180
+ titleGenPromptReset: '使用默认提示词',
181
+ titleGenSample: '测试消息',
182
+ titleGenTest: '测试生成',
183
+ titleGenTesting: '生成中…',
184
+ titleGenTestOk: '生成结果:',
185
+ titleGenTestFailed: '生成失败',
157
186
  featureWsRunning: '折叠项目运行提示(实验性)',
158
187
  featureWsRunningDesc: '折叠的项目里仍有会话在运行时,项目图标旋转提示;全部结束或展开项目后恢复。期间每 60 秒在后台短暂展开该项目复核运行状态再收起,会话行不显示,仅项目位置可能有约四分之一秒的轻微高度起伏。',
159
188
  tabPerformance: '性能',
@@ -228,10 +257,6 @@ const zh = {
228
257
  visionMoveDown: '下移',
229
258
  visionName: '名称',
230
259
  visionUseProvider: '供应商',
231
- visionUseProviderHint: '下拉选择或手动输入:session=跟随当前会话供应商,或供应商名/ID;设置后 baseUrl/API Key/格式自动取该供应商',
232
- visionUseProviderNone: '不跟随(自填地址)',
233
- visionUseProviderSession: '跟随当前会话(session)',
234
- visionUseProviderUnknown: '未找到该供应商,识别时会报错;请从下拉选择,或输入 session',
235
260
  visionSkipAfterFailures: '连续失败次数',
236
261
  visionSkipAfterFailuresHint: '某代理连续失败满次数后暂时跳过它,直接试下一个;0 = 不跳过',
237
262
  visionSkipMinutes: '跳过分钟数',
@@ -340,7 +365,6 @@ const zh = {
340
365
  upgradeDone: '已更新到 {v}',
341
366
  upgradeFinished: '升级完成',
342
367
  upgradeCheckFailed: '检查更新失败',
343
- version: '版本',
344
368
  close: '关闭',
345
369
  cancel: '取消',
346
370
  pathLabel: '路径',
@@ -385,6 +409,7 @@ const en = {
385
409
  tabFeatures: 'Features',
386
410
  tabStyles: 'Styles',
387
411
  tabProxy: 'Proxy',
412
+ tabBehavior: 'Behavior',
388
413
  tabAgents: 'Global Prompt',
389
414
  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.',
390
415
  agentsPlaceholder: 'Instructions followed by all projects by default; save empty to remove the global prompt',
@@ -408,12 +433,16 @@ const en = {
408
433
  proxyScopeSyncDesc: 'WebDAV upload and download go through the proxy. Off by default: domestic WebDAV providers work fine direct, and a stopped proxy breaks sync.',
409
434
  tabSync: 'Sync',
410
435
  tabDebug: 'Debug',
411
- 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.',
436
+ 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 (how many to keep is set in the "History" row; older ones are removed automatically after upload) and download lets you pick any of them. Data moves only when you click, never automatically.',
412
437
  syncUrlPlaceholder: 'https://dav.example.com/dav/',
413
- syncDir: '上传目录',
438
+ syncDir: 'Folder',
414
439
  syncDirPlaceholder: 'zcode-pro',
415
440
  syncLogin: 'Login',
416
441
  syncPassword: 'Password',
442
+ syncHistoryLimit: 'History',
443
+ syncHistoryLimitUnit: 'versions',
444
+ syncHistoryLimitHint: 'How many recent uploads keep their history versions on the server; older ones are removed automatically after a successful upload. The fixed-name latest file is never removed. 0 = keep no history versions.',
445
+ syncPruned: 'removed {n} older history versions',
417
446
  syncSave: 'Save',
418
447
  syncSaved: 'Sync settings saved.',
419
448
  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.',
@@ -496,6 +525,30 @@ const en = {
496
525
  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).',
497
526
  featureTitleLock: 'Keep renamed session titles',
498
527
  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.',
528
+ tabTitleGen: 'Task name prompt',
529
+ 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.',
530
+ titleGenEnabled: 'Enable',
531
+ titleGenProvider: 'Provider',
532
+ titleGenProviderNone: 'Custom endpoint (no provider)',
533
+ titleGenProviderSession: 'Follow current session',
534
+ titleGenProviderDeleted: ' (deleted)',
535
+ titleGenModel: 'Model',
536
+ titleGenModelHint: 'Pick from the list, or type a model id',
537
+ titleGenModelEmpty: '(not set)',
538
+ titleGenModelSessionHint: 'Pick from the list; the first entry follows the session model',
539
+ titleGenModelFollowSession: 'Follow the session model',
540
+ titleGenModelManualHint: 'Type a model id',
541
+ titleGenBaseUrl: 'Base URL',
542
+ titleGenApiKey: 'API Key',
543
+ titleGenFormat: 'Protocol',
544
+ titleGenPrompt: 'Prompt',
545
+ titleGenPromptPlaceholder: 'Leave empty for the built-in default prompt (button below shows it)',
546
+ titleGenPromptReset: 'Use default prompt',
547
+ titleGenSample: 'Test message',
548
+ titleGenTest: 'Test',
549
+ titleGenTesting: 'Generating…',
550
+ titleGenTestOk: 'Result: ',
551
+ titleGenTestFailed: 'Generation failed',
499
552
  featureWsRunning: 'Running indicator on collapsed projects (experimental)',
500
553
  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.',
501
554
  tabPerformance: 'Performance',
@@ -570,10 +623,6 @@ const en = {
570
623
  visionMoveDown: 'Down',
571
624
  visionName: 'Name',
572
625
  visionUseProvider: 'Provider',
573
- 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',
574
- visionUseProviderNone: 'Not following (enter base URL)',
575
- visionUseProviderSession: 'Follow session provider (session)',
576
- visionUseProviderUnknown: 'Unknown provider; recognition will fail. Pick from the list or type session',
577
626
  visionSkipAfterFailures: 'Skip after failures',
578
627
  visionSkipAfterFailuresHint: 'After this many consecutive failures a proxy is skipped and the next one is tried; 0 = never skip',
579
628
  visionSkipMinutes: 'Skip minutes',
@@ -682,7 +731,6 @@ const en = {
682
731
  upgradeDone: 'Updated to {v}',
683
732
  upgradeFinished: 'Update finished',
684
733
  upgradeCheckFailed: 'Update check failed',
685
- version: 'Version',
686
734
  close: 'Close',
687
735
  cancel: 'Cancel',
688
736
  pathLabel: 'Path',
@@ -855,7 +903,7 @@ export function observeRadixPopups(onPopup) {
855
903
  }
856
904
  // 兜底:直接观察 role=menu 的 content。延迟一帧再回调——Radix 偶尔分两帧渲染
857
905
  // (先挂 menu 容器、下一帧才填菜单项),立即回调时菜单项为空,调用方找不到
858
- // 锚点项就永远漏注入(菜单项填入不会再产生 role=menu 节点添加事件)
906
+ // 参照的菜单项就永远漏注入(菜单项填入不会再产生 role=menu 节点添加事件)
859
907
  if (node.getAttribute && node.getAttribute('role') === 'menu' && !seen.has(node)) {
860
908
  seen.add(node);
861
909
  requestAnimationFrame(() => {
@@ -8,6 +8,7 @@
8
8
  // 触发器/菜单的 React fiber props(OpenSplitButton 场景 target/fileLink/row.path)。
9
9
  import { t, closeRadixMenu, itemsOf, itemText, rpc } from '../core.js';
10
10
  import { getConfig } from '../core.js';
11
+ import { showToast } from '../ui.js';
11
12
 
12
13
  const COPY_ABS_TEXTS = ['复制绝对路径', 'Copy absolute path'];
13
14
  const NO_APPS_TEXTS = ['未找到可用 App', 'No apps found'];
@@ -126,6 +127,12 @@ export function handleFileMenu(content) {
126
127
  const path = resolveTargetPath(content);
127
128
  if (!path) return;
128
129
  const L = t();
130
+ // 打开失败(路径不存在等)弹 toast 报错,不再无声无息
131
+ const fire = (endpoint, label) => {
132
+ rpc(endpoint, { method: 'POST', body: { path } })
133
+ .then((r) => { if (r && r.ok === false) showToast(`${label}失败:${r.error || '未知错误'}`, 'error'); })
134
+ .catch(() => { /* 网络异常时 helper 多半未运行,此时菜单不会注入,静默 */ });
135
+ };
129
136
  // “默认应用打开”锚在编辑器列表末尾(无可用编辑器时即“未找到可用 App”禁用项)之上;
130
137
  // 找不到该组时退而锚在“复制绝对路径”上,保持“打开方式在前、路径操作在后”的次序
131
138
  const noApps = items.find((el) => NO_APPS_TEXTS.some((x) => itemText(el) === x))
@@ -135,13 +142,13 @@ export function handleFileMenu(content) {
135
142
  marker: 'file-open-default',
136
143
  label: L.fileOpenDefault,
137
144
  icon: ICON_OPEN_DEFAULT,
138
- onPick: () => { try { void rpc('/open-path', { method: 'POST', body: { path } }); } catch { /* ignore */ } },
145
+ onPick: () => { void fire('/open-path', L.fileOpenDefault); },
139
146
  });
140
147
  appendMenuItem(content, copyAbs, copyAbs, {
141
148
  marker: 'file-reveal',
142
149
  label: L.fileReveal,
143
150
  icon: ICON_REVEAL,
144
- onPick: () => { try { void rpc('/reveal-path', { method: 'POST', body: { path } }); } catch { /* ignore */ } },
151
+ onPick: () => { void fire('/reveal-path', L.fileReveal); },
145
152
  });
146
153
  })();
147
154
  }