codexmate 0.0.57 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,6 +143,7 @@ const en = Object.freeze({
143
143
  'side.config': 'Config',
144
144
  'side.sessions': 'Sessions',
145
145
  'side.prompts': 'Prompts',
146
+ 'side.prompts.meta': 'Prompt files and presets',
146
147
  'side.plugins': 'Plugins',
147
148
  'side.system': 'System',
148
149
  'side.orchestration': 'Tasks',
@@ -167,19 +168,21 @@ const en = Object.freeze({
167
168
  'side.update.currentOnly': 'Current v{current}',
168
169
  'side.update.retry': 'Retry version check',
169
170
  'side.config.codex': 'Codex',
170
- 'side.config.codex.meta': 'Provider / Model',
171
+ 'side.config.codex.meta': 'Provider · Model',
171
172
  'side.config.claude': 'Claude Code',
172
- 'side.config.claude.meta': 'Claude Settings',
173
+ 'side.config.claude.meta': 'Settings',
173
174
  'side.config.openclaw': 'OpenClaw',
174
- 'side.config.openclaw.meta': 'JSON5 / AGENTS',
175
+ 'side.config.openclaw.meta': 'JSON5 · AGENTS',
175
176
  'side.config.opencode': 'OpenCode',
176
- 'side.config.opencode.meta': 'Config / Provider',
177
+ 'side.config.opencode.meta': 'Provider',
177
178
  'side.sessions.browser': 'Session Browser',
178
179
  'side.sessions.browser.meta': 'Browse / Export / Cleanup',
179
180
  'side.prompts.agents': 'AGENTS.md',
180
181
  'side.prompts.agents.meta': 'Codex prompt file',
181
182
  'side.prompts.claude': 'CLAUDE.md',
182
183
  'side.prompts.claude.meta': 'Claude prompt file',
184
+ 'side.prompts.presets': 'Preset pool',
185
+ 'side.prompts.presets.meta': 'Save and paste presets',
183
186
  'side.plugins.tools': 'Prompt Tools',
184
187
  'side.plugins.tools.meta': 'Templates / Variables',
185
188
  'side.plugins.templatesCount': '{count} templates',
@@ -223,6 +226,32 @@ const en = Object.freeze({
223
226
  'subtitle.prompts': 'Edit AGENTS.md and CLAUDE.md.',
224
227
  'prompts.subTab.codex': 'AGENTS.md (Codex)',
225
228
  'prompts.subTab.project': 'CLAUDE.md',
229
+ 'prompts.subTab.presets': 'Preset pool',
230
+ 'prompts.presets.title': 'Presets',
231
+ 'prompts.presets.hint': 'Manage presets.',
232
+ 'prompts.presets.namePlaceholder': 'Preset name',
233
+ 'prompts.presets.selectPlaceholder': 'Choose preset…',
234
+ 'prompts.presets.saveCurrent': 'Save preset',
235
+ 'prompts.presets.empty': 'No presets yet',
236
+ 'prompts.presets.updatedAt': 'Updated: {time}',
237
+ 'prompts.presets.renameAria': 'Rename prompt preset',
238
+ 'prompts.presets.open': 'Open preset pool',
239
+ 'prompts.presets.addCurrent': 'Add to preset pool',
240
+ 'prompts.presets.defaultName.project': 'Project CLAUDE.md - {path}',
241
+ 'prompts.presets.error.emptyName': 'Preset name cannot be empty',
242
+ 'prompts.presets.error.emptyContent': 'Preset content cannot be empty',
243
+ 'prompts.presets.error.duplicateName': 'A preset with this name already exists',
244
+ 'prompts.presets.confirm.addCurrentTitle': 'Add to preset pool?',
245
+ 'prompts.presets.confirm.addCurrentMessage': 'Save as “{name}”.',
246
+ 'prompts.presets.confirm.overwriteTitle': 'Overwrite preset?',
247
+ 'prompts.presets.confirm.overwriteMessage': 'A preset named “{name}” already exists. Overwrite it with the current editor content?',
248
+ 'prompts.presets.confirm.overwriteConfirm': 'Overwrite',
249
+ 'prompts.presets.confirm.deleteTitle': 'Delete preset?',
250
+ 'prompts.presets.confirm.deleteMessage': 'Delete preset “{name}”? This cannot be undone.',
251
+ 'prompts.presets.toast.saved': 'Preset saved',
252
+ 'prompts.presets.toast.pasted': 'Pasted, not saved.',
253
+ 'prompts.presets.toast.renamed': 'Preset renamed',
254
+ 'prompts.presets.toast.deleted': 'Preset deleted',
226
255
  'prompts.project.pathLabel': 'Project path (optional)',
227
256
  'prompts.project.selectPlaceholder': '-- Global (~/.claude/CLAUDE.md) --',
228
257
  'prompts.project.manualPlaceholder': 'Or enter a project root path...',
@@ -488,6 +517,8 @@ const en = Object.freeze({
488
517
  'modal.claudeConfigEdit.title': 'Edit Claude Code config',
489
518
  'field.useBuiltinTransform': 'Use built-in transform (OpenAI compatible)',
490
519
  'hint.useBuiltinTransform': 'When enabled, base_url points to codexmate built-in transform service; Codex token is fixed to codexmate.',
520
+ 'field.transformMaxRetries': 'Built-in transform retries',
521
+ 'hint.transformMaxRetries': 'Default 2, minimum 2; number of retries after the first failed attempt.',
491
522
 
492
523
  // Config template / agents modals
493
524
  'modal.configTemplate.label': 'config.toml template',
@@ -144,6 +144,7 @@ const ja = Object.freeze({
144
144
  'side.config': '設定',
145
145
  'side.sessions': 'セッション',
146
146
  'side.prompts': 'Prompts',
147
+ 'side.prompts.meta': 'プロンプトファイルとプリセット',
147
148
  'side.plugins': 'プラグイン',
148
149
  'side.system': 'システム',
149
150
  'side.orchestration': 'タスク',
@@ -168,19 +169,21 @@ const ja = Object.freeze({
168
169
  'side.update.currentOnly': '現在 v{current}',
169
170
  'side.update.retry': 'バージョン確認を再試行',
170
171
  'side.config.codex': 'Codex',
171
- 'side.config.codex.meta': 'Provider / Model',
172
+ 'side.config.codex.meta': 'Provider · Model',
172
173
  'side.config.claude': 'Claude Code',
173
- 'side.config.claude.meta': 'Claude Settings',
174
+ 'side.config.claude.meta': 'Settings',
174
175
  'side.config.openclaw': 'OpenClaw',
175
- 'side.config.openclaw.meta': 'JSON5 / AGENTS',
176
+ 'side.config.openclaw.meta': 'JSON5 · AGENTS',
176
177
  'side.config.opencode': 'OpenCode',
177
- 'side.config.opencode.meta': 'Config / Provider',
178
+ 'side.config.opencode.meta': 'Provider',
178
179
  'side.sessions.browser': 'セッション閲覧',
179
180
  'side.sessions.browser.meta': '閲覧 / エクスポート / クリーンアップ',
180
181
  'side.prompts.agents': 'AGENTS.md',
181
182
  'side.prompts.agents.meta': 'Codex プロンプトファイル',
182
183
  'side.prompts.claude': 'CLAUDE.md',
183
184
  'side.prompts.claude.meta': 'Claude プロンプトファイル',
185
+ 'side.prompts.presets': 'プリセットプール',
186
+ 'side.prompts.presets.meta': 'プリセットを保存・貼り付け',
184
187
  'side.plugins.tools': 'プロンプトツール',
185
188
  'side.plugins.tools.meta': 'テンプレート / 変数',
186
189
  'side.plugins.templatesCount': '{count} 件のテンプレート',
@@ -224,6 +227,32 @@ const ja = Object.freeze({
224
227
  'subtitle.prompts': 'AGENTS.md と CLAUDE.md を編集。',
225
228
  'prompts.subTab.codex': 'AGENTS.md (Codex)',
226
229
  'prompts.subTab.project': 'CLAUDE.md',
230
+ 'prompts.subTab.presets': 'プリセット',
231
+ 'prompts.presets.title': 'プリセット',
232
+ 'prompts.presets.hint': 'プリセットを管理します。',
233
+ 'prompts.presets.namePlaceholder': 'プリセット名',
234
+ 'prompts.presets.selectPlaceholder': 'プリセットを選択…',
235
+ 'prompts.presets.saveCurrent': 'プリセット保存',
236
+ 'prompts.presets.empty': 'プリセットはありません',
237
+ 'prompts.presets.updatedAt': '更新: {time}',
238
+ 'prompts.presets.renameAria': 'prompt プリセット名を変更',
239
+ 'prompts.presets.open': 'プリセットを開く',
240
+ 'prompts.presets.addCurrent': 'プリセットプールに追加',
241
+ 'prompts.presets.defaultName.project': 'プロジェクト CLAUDE.md - {path}',
242
+ 'prompts.presets.error.emptyName': 'プリセット名は空にできません',
243
+ 'prompts.presets.error.emptyContent': 'プリセット内容は空にできません',
244
+ 'prompts.presets.error.duplicateName': '同じ名前のプリセットが既に存在します',
245
+ 'prompts.presets.confirm.addCurrentTitle': 'プリセットプールに追加しますか?',
246
+ 'prompts.presets.confirm.addCurrentMessage': '「{name}」として保存します。',
247
+ 'prompts.presets.confirm.overwriteTitle': 'プリセットを上書きしますか?',
248
+ 'prompts.presets.confirm.overwriteMessage': '「{name}」というプリセットは既に存在します。現在のエディター内容で上書きしますか?',
249
+ 'prompts.presets.confirm.overwriteConfirm': '上書き',
250
+ 'prompts.presets.confirm.deleteTitle': 'プリセットを削除しますか?',
251
+ 'prompts.presets.confirm.deleteMessage': 'プリセット「{name}」を削除しますか?この操作は元に戻せません。',
252
+ 'prompts.presets.toast.saved': 'プリセットを保存しました',
253
+ 'prompts.presets.toast.pasted': '貼り付けました。未保存です。',
254
+ 'prompts.presets.toast.renamed': 'プリセット名を変更しました',
255
+ 'prompts.presets.toast.deleted': 'プリセットを削除しました',
227
256
  'prompts.project.pathLabel': 'プロジェクトパス(任意)',
228
257
  'prompts.project.selectPlaceholder': '-- グローバル (~/.claude/CLAUDE.md) --',
229
258
  'prompts.project.manualPlaceholder': 'またはプロジェクトルートパスを入力...',
@@ -490,6 +519,8 @@ const ja = Object.freeze({
490
519
  'modal.claudeConfigEdit.title': 'Claude Code 設定編集',
491
520
  'field.useBuiltinTransform': '内蔵変換を使用(OpenAI 形式互換)',
492
521
  'hint.useBuiltinTransform': '有効時:書き込まれる base_url は codexmate 内蔵変換サービスを指します。Codex のトークンは codexmate に固定されます。',
522
+ 'field.transformMaxRetries': '内蔵変換の再試行回数',
523
+ 'hint.transformMaxRetries': '既定値は 2、最小値も 2。初回失敗後に再試行する最大回数です。',
493
524
 
494
525
  // Config template / agents modals
495
526
  'modal.configTemplate.label': 'config.toml テンプレート',
@@ -104,6 +104,7 @@ const vi = Object.freeze({
104
104
  'side.config': 'Cấu hình',
105
105
  'side.sessions': 'Phiên',
106
106
  'side.prompts': 'Prompts',
107
+ 'side.prompts.meta': 'Tệp prompt và preset',
107
108
  'side.plugins': 'Plugin',
108
109
  'side.system': 'Hệ thống',
109
110
  'side.orchestration': 'Tác vụ',
@@ -128,19 +129,21 @@ const vi = Object.freeze({
128
129
  'side.update.currentOnly': 'Hiện tại v{current}',
129
130
  'side.update.retry': 'Thử kiểm tra phiên bản lại',
130
131
  'side.config.codex': 'Codex',
131
- 'side.config.codex.meta': 'Provider / Model',
132
+ 'side.config.codex.meta': 'Provider · Model',
132
133
  'side.config.claude': 'Claude Code',
133
- 'side.config.claude.meta': 'Cài đặt Claude',
134
+ 'side.config.claude.meta': 'Settings',
134
135
  'side.config.openclaw': 'OpenClaw',
135
- 'side.config.openclaw.meta': 'JSON5 / AGENTS',
136
+ 'side.config.openclaw.meta': 'JSON5 · AGENTS',
136
137
  'side.config.opencode': 'OpenCode',
137
- 'side.config.opencode.meta': 'Config / Provider',
138
+ 'side.config.opencode.meta': 'Provider',
138
139
  'side.sessions.browser': 'Trình duyệt phiên',
139
140
  'side.sessions.browser.meta': 'Duyệt / Xuất / Dọn dẹp',
140
141
  'side.prompts.agents': 'AGENTS.md',
141
142
  'side.prompts.agents.meta': 'Tệp lệnh Codex',
142
143
  'side.prompts.claude': 'CLAUDE.md',
143
144
  'side.prompts.claude.meta': 'Tệp lệnh Claude',
145
+ 'side.prompts.presets': 'Kho preset',
146
+ 'side.prompts.presets.meta': 'Preset prompt tái sử dụng',
144
147
  'side.plugins.tools': 'Công cụ prompt',
145
148
  'side.plugins.tools.meta': 'Mẫu / Biến',
146
149
  'side.plugins.templatesCount': '{count} mẫu',
@@ -238,6 +241,32 @@ const vi = Object.freeze({
238
241
  'subtitle.prompts': 'Chỉnh sửa AGENTS.md và CLAUDE.md.',
239
242
  'prompts.subTab.codex': 'AGENTS.md (Codex)',
240
243
  'prompts.subTab.project': 'CLAUDE.md',
244
+ 'prompts.subTab.presets': 'Kho preset',
245
+ 'prompts.presets.title': 'Preset',
246
+ 'prompts.presets.hint': 'Quản lý preset.',
247
+ 'prompts.presets.namePlaceholder': 'Tên preset',
248
+ 'prompts.presets.selectPlaceholder': 'Chọn preset…',
249
+ 'prompts.presets.saveCurrent': 'Lưu preset',
250
+ 'prompts.presets.empty': 'Chưa có preset',
251
+ 'prompts.presets.updatedAt': 'Cập nhật: {time}',
252
+ 'prompts.presets.renameAria': 'Đổi tên preset prompt',
253
+ 'prompts.presets.open': 'Mở kho preset',
254
+ 'prompts.presets.addCurrent': 'Thêm vào kho preset',
255
+ 'prompts.presets.defaultName.project': 'CLAUDE.md dự án - {path}',
256
+ 'prompts.presets.error.emptyName': 'Tên preset không được để trống',
257
+ 'prompts.presets.error.emptyContent': 'Nội dung preset không được để trống',
258
+ 'prompts.presets.error.duplicateName': 'Đã có preset trùng tên',
259
+ 'prompts.presets.confirm.addCurrentTitle': 'Thêm vào kho preset?',
260
+ 'prompts.presets.confirm.addCurrentMessage': 'Lưu thành “{name}”.',
261
+ 'prompts.presets.confirm.overwriteTitle': 'Ghi đè preset?',
262
+ 'prompts.presets.confirm.overwriteMessage': 'Preset “{name}” đã tồn tại. Ghi đè bằng nội dung editor hiện tại?',
263
+ 'prompts.presets.confirm.overwriteConfirm': 'Ghi đè',
264
+ 'prompts.presets.confirm.deleteTitle': 'Xóa preset?',
265
+ 'prompts.presets.confirm.deleteMessage': 'Xóa preset “{name}”? Không thể hoàn tác.',
266
+ 'prompts.presets.toast.saved': 'Đã lưu preset',
267
+ 'prompts.presets.toast.pasted': 'Đã dán, chưa lưu.',
268
+ 'prompts.presets.toast.renamed': 'Đã đổi tên preset',
269
+ 'prompts.presets.toast.deleted': 'Đã xóa preset',
241
270
  'prompts.project.pathLabel': 'Đường dẫn dự án (tùy chọn)',
242
271
  'prompts.project.selectPlaceholder': '-- Toàn cục (~/.claude/CLAUDE.md) --',
243
272
  'prompts.project.manualPlaceholder': 'Hoặc nhập đường dẫn gốc dự án...',
@@ -708,6 +737,8 @@ const vi = Object.freeze({
708
737
  'modal.claudeConfigEdit.title': 'Chỉnh sửa cấu hình Claude Code',
709
738
  'field.useBuiltinTransform': 'Dùng transform tích hợp (tương thích OpenAI)',
710
739
  'hint.useBuiltinTransform': 'Khi bật, base_url trỏ đến dịch vụ transform tích hợp của codexmate.',
740
+ 'field.transformMaxRetries': 'Số lần thử lại transform tích hợp',
741
+ 'hint.transformMaxRetries': 'Mặc định 2, tối thiểu 2; số lần thử lại sau lần gọi đầu thất bại.',
711
742
  'modal.configTemplate.title': 'Trình soạn thảo template cấu hình (xác nhận thủ công)',
712
743
  'modal.configTemplate.label': 'Template config.toml',
713
744
  'modal.configTemplate.placeholder': 'Chỉnh sửa template config.toml tại đây',
@@ -143,6 +143,7 @@ const zhTw = Object.freeze({
143
143
  'side.config': '設定',
144
144
  'side.sessions': '會話',
145
145
  'side.prompts': 'Prompts',
146
+ 'side.prompts.meta': 'Prompt 文件與預設',
146
147
  'side.plugins': '插件',
147
148
  'side.system': '系統',
148
149
  'side.orchestration': '任務',
@@ -167,19 +168,21 @@ const zhTw = Object.freeze({
167
168
  'side.update.currentOnly': '目前 v{current}',
168
169
  'side.update.retry': '重試版本檢查',
169
170
  'side.config.codex': 'Codex',
170
- 'side.config.codex.meta': 'Provider / Model',
171
+ 'side.config.codex.meta': 'Provider · Model',
171
172
  'side.config.claude': 'Claude Code',
172
- 'side.config.claude.meta': 'Claude Settings',
173
+ 'side.config.claude.meta': 'Settings',
173
174
  'side.config.openclaw': 'OpenClaw',
174
- 'side.config.openclaw.meta': 'JSON5 / AGENTS',
175
+ 'side.config.openclaw.meta': 'JSON5 · AGENTS',
175
176
  'side.config.opencode': 'OpenCode',
176
- 'side.config.opencode.meta': '設定 / Provider',
177
+ 'side.config.opencode.meta': 'Provider',
177
178
  'side.sessions.browser': '會話瀏覽',
178
179
  'side.sessions.browser.meta': '瀏覽 / 匯出 / 清理',
179
180
  'side.prompts.agents': 'AGENTS.md',
180
181
  'side.prompts.agents.meta': 'Codex 指令文件',
181
182
  'side.prompts.claude': 'CLAUDE.md',
182
183
  'side.prompts.claude.meta': 'Claude 指令文件',
184
+ 'side.prompts.presets': '預設池',
185
+ 'side.prompts.presets.meta': '儲存和貼上預設',
183
186
  'side.plugins.tools': '提示詞工具',
184
187
  'side.plugins.tools.meta': '模板 / 變量',
185
188
  'side.plugins.templatesCount': '{count} 個模板',
@@ -223,6 +226,32 @@ const zhTw = Object.freeze({
223
226
  'subtitle.prompts': '編輯 AGENTS.md 與 CLAUDE.md。',
224
227
  'prompts.subTab.codex': 'AGENTS.md (Codex)',
225
228
  'prompts.subTab.project': 'CLAUDE.md',
229
+ 'prompts.subTab.presets': '預設池',
230
+ 'prompts.presets.title': '預設池',
231
+ 'prompts.presets.hint': '管理預設。',
232
+ 'prompts.presets.namePlaceholder': '預設名稱',
233
+ 'prompts.presets.selectPlaceholder': '選擇預設…',
234
+ 'prompts.presets.saveCurrent': '存為預設',
235
+ 'prompts.presets.empty': '暫無預設',
236
+ 'prompts.presets.updatedAt': '更新時間:{time}',
237
+ 'prompts.presets.renameAria': '重新命名 prompt 預設',
238
+ 'prompts.presets.open': '打開預設池',
239
+ 'prompts.presets.addCurrent': '加入預設池',
240
+ 'prompts.presets.defaultName.project': '專案 CLAUDE.md - {path}',
241
+ 'prompts.presets.error.emptyName': '預設名稱不能為空',
242
+ 'prompts.presets.error.emptyContent': '預設內容不能為空',
243
+ 'prompts.presets.error.duplicateName': '已存在同名預設',
244
+ 'prompts.presets.confirm.addCurrentTitle': '加入預設池?',
245
+ 'prompts.presets.confirm.addCurrentMessage': '存為「{name}」。',
246
+ 'prompts.presets.confirm.overwriteTitle': '覆蓋預設?',
247
+ 'prompts.presets.confirm.overwriteMessage': '名為「{name}」的預設已存在。要用目前編輯器內容覆蓋它嗎?',
248
+ 'prompts.presets.confirm.overwriteConfirm': '覆蓋',
249
+ 'prompts.presets.confirm.deleteTitle': '刪除預設?',
250
+ 'prompts.presets.confirm.deleteMessage': '刪除預設「{name}」?此操作不可復原。',
251
+ 'prompts.presets.toast.saved': '預設已保存',
252
+ 'prompts.presets.toast.pasted': '已貼上,未儲存。',
253
+ 'prompts.presets.toast.renamed': '預設已重新命名',
254
+ 'prompts.presets.toast.deleted': '預設已刪除',
226
255
  'prompts.project.pathLabel': '專案路徑(可選)',
227
256
  'prompts.project.selectPlaceholder': '-- 全域 (~/.claude/CLAUDE.md) --',
228
257
  'prompts.project.manualPlaceholder': '或手動輸入專案根路徑...',
@@ -488,6 +517,8 @@ const zhTw = Object.freeze({
488
517
  'modal.claudeConfigEdit.title': '編輯 Claude Code 設定',
489
518
  'field.useBuiltinTransform': '使用內建轉換(兼容 OpenAI 格式)',
490
519
  'hint.useBuiltinTransform': '開啟後:寫入的 base_url 會指向 codexmate 內建轉換服務;Codex 使用的令牌固定為 codexmate。',
520
+ 'field.transformMaxRetries': '內建轉換重試次數',
521
+ 'hint.transformMaxRetries': '預設 2,最小 2;表示失敗後最多重試的次數。',
491
522
 
492
523
  // Config template / agents modals
493
524
  'modal.configTemplate.label': 'config.toml 模板',
@@ -143,6 +143,7 @@ const zh = Object.freeze({
143
143
  'side.config': '配置',
144
144
  'side.sessions': '会话',
145
145
  'side.prompts': 'Prompts',
146
+ 'side.prompts.meta': 'Prompt 文件与预设',
146
147
  'side.plugins': '插件',
147
148
  'side.system': '系统',
148
149
  'side.orchestration': '任务',
@@ -167,19 +168,21 @@ const zh = Object.freeze({
167
168
  'side.update.currentOnly': '当前 v{current}',
168
169
  'side.update.retry': '重试版本检查',
169
170
  'side.config.codex': 'Codex',
170
- 'side.config.codex.meta': 'Provider / Model',
171
+ 'side.config.codex.meta': 'Provider · Model',
171
172
  'side.config.claude': 'Claude Code',
172
- 'side.config.claude.meta': 'Claude Settings',
173
+ 'side.config.claude.meta': 'Settings',
173
174
  'side.config.openclaw': 'OpenClaw',
174
- 'side.config.openclaw.meta': 'JSON5 / AGENTS',
175
+ 'side.config.openclaw.meta': 'JSON5 · AGENTS',
175
176
  'side.config.opencode': 'OpenCode',
176
- 'side.config.opencode.meta': '配置 / Provider',
177
+ 'side.config.opencode.meta': 'Provider',
177
178
  'side.sessions.browser': '会话浏览',
178
179
  'side.sessions.browser.meta': '浏览 / 导出 / 清理',
179
180
  'side.prompts.agents': 'AGENTS.md',
180
181
  'side.prompts.agents.meta': 'Codex 指令文件',
181
182
  'side.prompts.claude': 'CLAUDE.md',
182
183
  'side.prompts.claude.meta': 'Claude 指令文件',
184
+ 'side.prompts.presets': '预设池',
185
+ 'side.prompts.presets.meta': '保存和粘贴预设',
183
186
  'side.plugins.tools': '提示词工具',
184
187
  'side.plugins.tools.meta': '模板 / 变量',
185
188
  'side.plugins.templatesCount': '{count} 个模板',
@@ -223,6 +226,32 @@ const zh = Object.freeze({
223
226
  'subtitle.prompts': '编辑 AGENTS.md 与 CLAUDE.md。',
224
227
  'prompts.subTab.codex': 'AGENTS.md (Codex)',
225
228
  'prompts.subTab.project': 'CLAUDE.md',
229
+ 'prompts.subTab.presets': '预设池',
230
+ 'prompts.presets.title': '预设池',
231
+ 'prompts.presets.hint': '管理预设。',
232
+ 'prompts.presets.namePlaceholder': '预设名称',
233
+ 'prompts.presets.selectPlaceholder': '选择预设…',
234
+ 'prompts.presets.saveCurrent': '存为预设',
235
+ 'prompts.presets.empty': '暂无预设',
236
+ 'prompts.presets.updatedAt': '更新时间:{time}',
237
+ 'prompts.presets.renameAria': '重命名 prompt 预设',
238
+ 'prompts.presets.open': '打开预设池',
239
+ 'prompts.presets.addCurrent': '添加到预设池',
240
+ 'prompts.presets.defaultName.project': '项目 CLAUDE.md - {path}',
241
+ 'prompts.presets.error.emptyName': '预设名称不能为空',
242
+ 'prompts.presets.error.emptyContent': '预设内容不能为空',
243
+ 'prompts.presets.error.duplicateName': '已存在同名预设',
244
+ 'prompts.presets.confirm.addCurrentTitle': '添加到预设池?',
245
+ 'prompts.presets.confirm.addCurrentMessage': '保存为“{name}”。',
246
+ 'prompts.presets.confirm.overwriteTitle': '覆盖预设?',
247
+ 'prompts.presets.confirm.overwriteMessage': '名为“{name}”的预设已存在。要用当前编辑器内容覆盖它吗?',
248
+ 'prompts.presets.confirm.overwriteConfirm': '覆盖',
249
+ 'prompts.presets.confirm.deleteTitle': '删除预设?',
250
+ 'prompts.presets.confirm.deleteMessage': '删除预设“{name}”?此操作不可撤销。',
251
+ 'prompts.presets.toast.saved': '预设已保存',
252
+ 'prompts.presets.toast.pasted': '已粘贴,未保存。',
253
+ 'prompts.presets.toast.renamed': '预设已重命名',
254
+ 'prompts.presets.toast.deleted': '预设已删除',
226
255
  'prompts.project.pathLabel': '项目路径(可选)',
227
256
  'prompts.project.selectPlaceholder': '-- 全局 (~/.claude/CLAUDE.md) --',
228
257
  'prompts.project.manualPlaceholder': '或手动输入项目根路径...',
@@ -488,6 +517,8 @@ const zh = Object.freeze({
488
517
  'modal.claudeConfigEdit.title': '编辑 Claude Code 配置',
489
518
  'field.useBuiltinTransform': '使用内建转换(兼容 OpenAI 格式)',
490
519
  'hint.useBuiltinTransform': '开启后:写入的 base_url 会指向 codexmate 内建转换服务;Codex 使用的令牌固定为 codexmate。',
520
+ 'field.transformMaxRetries': '内建转换重试次数',
521
+ 'hint.transformMaxRetries': '默认 2,最小 2;表示失败后最多重试的次数。',
491
522
 
492
523
  // Config template / agents modals
493
524
  'modal.configTemplate.label': 'config.toml 模板',
@@ -251,40 +251,23 @@
251
251
  <span v-if="opencodeModel">{{ t('common.current', { value: opencodeModel }) }}</span>
252
252
  </div>
253
253
  </button>
254
- </div>
255
-
256
- <div class="side-section" role="navigation" :aria-label="t('side.prompts')">
257
- <div class="side-section-title">{{ t('side.prompts') }}</div>
258
254
  <button
259
- id="side-tab-prompts-agents"
255
+ id="side-tab-prompts"
260
256
  data-main-tab="prompts"
261
- data-prompts-sub-tab="codex"
262
- :aria-current="mainTab === 'prompts' && promptsSubTab === 'codex' ? 'page' : null"
263
- :class="['side-item', { active: isMainTabNavActive('prompts') && promptsSubTab === 'codex' }]"
257
+ :aria-current="mainTab === 'prompts' ? 'page' : null"
258
+ :class="['side-item', { active: isMainTabNavActive('prompts') }]"
264
259
  @pointerdown="onMainTabPointerDown('prompts', $event)"
265
- @click="switchPromptsSubTab('codex'); onMainTabClick('prompts')">
260
+ @click="onMainTabClick('prompts', $event)">
266
261
  <span class="side-item-icon" aria-hidden="true">P</span>
267
- <div class="side-item-title">{{ t('side.prompts.agents') }}</div>
268
- <div class="side-item-meta">
269
- <span>{{ t('side.prompts.agents.meta') }}</span>
270
- </div>
271
- </button>
272
- <button
273
- id="side-tab-prompts-project"
274
- data-main-tab="prompts"
275
- data-prompts-sub-tab="claude-project"
276
- :aria-current="mainTab === 'prompts' && promptsSubTab === 'claude-project' ? 'page' : null"
277
- :class="['side-item', { active: isMainTabNavActive('prompts') && promptsSubTab === 'claude-project' }]"
278
- @pointerdown="onMainTabPointerDown('prompts', $event)"
279
- @click="switchPromptsSubTab('claude-project'); onMainTabClick('prompts')">
280
- <span class="side-item-icon" aria-hidden="true">M</span>
281
- <div class="side-item-title">{{ t('side.prompts.claude') }}</div>
262
+ <div class="side-item-title">{{ t('side.prompts') }}</div>
282
263
  <div class="side-item-meta">
283
- <span>{{ t('side.prompts.claude.meta') }}</span>
264
+ <span>{{ t('side.prompts.meta') }}</span>
284
265
  </div>
285
266
  </button>
267
+
286
268
  </div>
287
269
 
270
+
288
271
  <div class="side-section" role="navigation" :aria-label="t('side.sessions')">
289
272
  <div class="side-section-title">{{ t('side.sessions') }}</div>
290
273
  <button
@@ -53,6 +53,19 @@
53
53
  {{ t('field.useBuiltinTransform') }}
54
54
  </label>
55
55
  </div>
56
+ <div class="form-group" v-if="newProvider.useTransform">
57
+ <label class="form-label">{{ t('field.transformMaxRetries') }}</label>
58
+ <input
59
+ v-model.number="newProvider.openaiBridgeMaxRetries"
60
+ type="number"
61
+ min="2"
62
+ max="10"
63
+ step="1"
64
+ :class="['form-input', { invalid: !!providerFieldError('add', 'openaiBridgeMaxRetries') }]"
65
+ @blur="normalizeProviderDraft('add')">
66
+ <div class="form-hint">{{ t('hint.transformMaxRetries') }}</div>
67
+ <div v-if="providerFieldError('add', 'openaiBridgeMaxRetries')" class="form-hint form-error">{{ providerFieldError('add', 'openaiBridgeMaxRetries') }}</div>
68
+ </div>
56
69
 
57
70
  <div class="btn-group">
58
71
  <button class="btn btn-cancel" @click="closeAddModal">{{ t('common.cancel') }}</button>
@@ -91,6 +104,19 @@
91
104
  </button>
92
105
  </div>
93
106
  </div>
107
+ <div class="form-group" v-if="editingProvider.useTransform">
108
+ <label class="form-label">{{ t('field.transformMaxRetries') }}</label>
109
+ <input
110
+ v-model.number="editingProvider.openaiBridgeMaxRetries"
111
+ type="number"
112
+ min="2"
113
+ max="10"
114
+ step="1"
115
+ :class="['form-input', { invalid: !!providerFieldError('edit', 'openaiBridgeMaxRetries') }]"
116
+ @blur="normalizeProviderDraft('edit')">
117
+ <div class="form-hint">{{ t('hint.transformMaxRetries') }}</div>
118
+ <div v-if="providerFieldError('edit', 'openaiBridgeMaxRetries')" class="form-hint form-error">{{ providerFieldError('edit', 'openaiBridgeMaxRetries') }}</div>
119
+ </div>
94
120
 
95
121
  <div class="btn-group">
96
122
  <button class="btn btn-cancel" @click="closeEditModal">{{ t('common.cancel') }}</button>
@@ -5,9 +5,9 @@
5
5
  id="panel-prompts"
6
6
  role="tabpanel"
7
7
  aria-labelledby="tab-prompts">
8
- <div class="segmented-control">
9
- <button type="button" :class="['segment', { active: promptsSubTab === 'codex' }]" @click="switchPromptsSubTab('codex')">{{ t('prompts.subTab.codex') }}</button>
10
- <button type="button" :class="['segment', { active: promptsSubTab === 'claude-project' }]" @click="switchPromptsSubTab('claude-project')">{{ t('prompts.subTab.project') }}</button>
8
+ <div class="prompts-md-tabs" role="tablist" :aria-label="t('tab.prompts')">
9
+ <button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'codex' }]" role="tab" :aria-selected="promptsSubTab === 'codex'" @click="switchPromptsSubTab('codex')">{{ t('prompts.subTab.codex') }}</button>
10
+ <button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'claude-project' }]" role="tab" :aria-selected="promptsSubTab === 'claude-project'" @click="switchPromptsSubTab('claude-project')">{{ t('prompts.subTab.project') }}</button>
11
11
  </div>
12
12
 
13
13
  <div v-if="promptsSubTab === 'claude-project'" class="project-path-selector">
@@ -32,6 +32,7 @@
32
32
  </div>
33
33
  </div>
34
34
 
35
+
35
36
  <div class="prompts-editor">
36
37
  <div class="prompts-editor-toolbar">
37
38
  <div class="form-hint">
@@ -83,6 +84,68 @@
83
84
  </div>
84
85
  </div>
85
86
  </div>
87
+ <div class="prompt-presets-inline-row">
88
+ <div class="prompt-presets-inline-group">
89
+ <label class="prompt-presets-inline-label">{{ t('prompts.presets.title') }}</label>
90
+ <select
91
+ class="form-input prompt-presets-select"
92
+ :disabled="agentsLoading || agentsSaving || agentsDiffVisible || !promptPresets.length"
93
+ :title="t('prompts.presets.title')"
94
+ @change="applyPromptPresetSelection($event)">
95
+ <option value="">{{ t('prompts.presets.selectPlaceholder') }}</option>
96
+ <option v-for="preset in promptPresets" :key="preset.id" :value="preset.id">{{ preset.name }}</option>
97
+ </select>
98
+ </div>
99
+ <div class="prompt-presets-inline-group prompt-presets-inline-group--save">
100
+ <input
101
+ type="text"
102
+ class="form-input prompt-presets-name-input"
103
+ v-model="promptPresetNameDraft"
104
+ :placeholder="t('prompts.presets.namePlaceholder')"
105
+ :disabled="agentsLoading || agentsSaving || agentsDiffVisible"
106
+ @keydown.enter.prevent="saveCurrentPromptAsPreset">
107
+ <button
108
+ type="button"
109
+ class="btn-mini btn-confirm-mini"
110
+ @click="saveCurrentPromptAsPreset"
111
+ :disabled="promptPresetSaving || agentsLoading || agentsSaving || agentsDiffVisible"
112
+ :title="t('prompts.presets.saveCurrent')">
113
+ {{ t('prompts.presets.saveCurrent') }}
114
+ </button>
115
+ </div>
116
+ </div>
117
+ <details class="prompt-presets-panel">
118
+ <summary class="prompt-presets-summary">
119
+ <span>{{ t('prompts.presets.title') }}</span>
120
+ <small>{{ t('prompts.presets.hint') }}</small>
121
+ </summary>
122
+ <div class="form-group prompt-presets-body">
123
+ <div class="editor-frame prompt-presets-frame">
124
+ <div v-if="!promptPresets.length" class="state-message prompt-presets-empty">{{ t('prompts.presets.empty') }}</div>
125
+ <div v-else class="prompt-presets-list">
126
+ <article v-for="preset in promptPresets" :key="preset.id" class="prompt-preset-row">
127
+ <div class="prompt-preset-main">
128
+ <input
129
+ type="text"
130
+ class="form-input prompt-preset-name"
131
+ :value="getPromptPresetRenameDraft(preset)"
132
+ @input="setPromptPresetRenameDraft(preset.id, $event.target.value)"
133
+ @keydown.enter.prevent="renamePromptPreset(preset)"
134
+ :aria-label="t('prompts.presets.renameAria')">
135
+ <div class="form-hint">{{ t('prompts.presets.updatedAt', { time: formatPromptPresetTime(preset.updatedAt) }) }}</div>
136
+ <pre class="prompt-preset-preview">{{ preset.content }}</pre>
137
+ </div>
138
+ <div class="prompts-editor-actions prompt-preset-actions">
139
+ <button type="button" class="btn-mini" @click="renamePromptPreset(preset)">{{ t('common.save') }}</button>
140
+ <button type="button" class="btn-mini" @click="applyPromptPresetToEditor(preset)">{{ t('common.paste') }}</button>
141
+ <button type="button" class="btn-mini btn-danger-mini" @click="deletePromptPreset(preset)">{{ t('common.delete') }}</button>
142
+ </div>
143
+ </article>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </details>
148
+
86
149
 
87
150
  <div class="form-group">
88
151
  <div v-if="agentsDiffVisible">