codexmate 0.0.42 → 0.0.44
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.md +2 -0
- package/README.zh.md +2 -0
- package/cli/claude-proxy.js +611 -14
- package/cli/update.js +77 -7
- package/cli.js +191 -23
- package/package.json +2 -2
- package/web-ui/app.js +39 -10
- package/web-ui/logic.claude.mjs +65 -2
- package/web-ui/logic.runtime.mjs +0 -7
- package/web-ui/modules/app.methods.agents.mjs +6 -6
- package/web-ui/modules/app.methods.claude-config.mjs +65 -49
- package/web-ui/modules/app.methods.codex-config.mjs +10 -10
- package/web-ui/modules/app.methods.index.mjs +1 -1
- package/web-ui/modules/app.methods.install.mjs +129 -1
- package/web-ui/modules/app.methods.openclaw-persist.mjs +1 -1
- package/web-ui/modules/app.methods.providers.mjs +17 -16
- package/web-ui/modules/app.methods.runtime.mjs +27 -21
- package/web-ui/modules/app.methods.session-actions.mjs +25 -20
- package/web-ui/modules/app.methods.session-timeline.mjs +0 -1
- package/web-ui/modules/app.methods.startup-claude.mjs +29 -3
- package/web-ui/modules/app.methods.tool-config-permissions.mjs +3 -0
- package/web-ui/modules/i18n/locales/en.mjs +65 -1
- package/web-ui/modules/i18n/locales/ja.mjs +65 -1
- package/web-ui/modules/i18n/locales/vi.mjs +77 -2
- package/web-ui/modules/i18n/locales/zh.mjs +66 -2
- package/web-ui/partials/index/layout-header.html +24 -0
- package/web-ui/partials/index/modals-basic.html +18 -1
- package/web-ui/partials/index/panel-config-claude.html +5 -2
- package/web-ui/partials/index/panel-config-codex.html +2 -1
- package/web-ui/res/web-ui-render.precompiled.js +115 -22
- package/web-ui/styles/controls-forms.css +5 -5
- package/web-ui/styles/layout-shell.css +145 -0
- package/web-ui/styles/responsive.css +12 -0
- package/web-ui/styles/titles-cards.css +10 -4
|
@@ -61,6 +61,8 @@ const en = Object.freeze({
|
|
|
61
61
|
'common.notExistsWillCreateOnApply': 'Not found. Will be created on apply.',
|
|
62
62
|
'common.notExistsWillCreateOnSave': 'Not found. Will be created on save.',
|
|
63
63
|
'common.none': 'None',
|
|
64
|
+
'common.configured': 'Configured',
|
|
65
|
+
'common.notConfigured': 'Not configured',
|
|
64
66
|
'cli.missing.title': '{name} CLI not installed',
|
|
65
67
|
'cli.missing.subtitle': 'Install {name} CLI before using this page.',
|
|
66
68
|
'cli.missing.openDocs': 'Open install guide',
|
|
@@ -143,6 +145,17 @@ const en = Object.freeze({
|
|
|
143
145
|
'side.overview.doctor.meta': 'Overview / Diagnostics',
|
|
144
146
|
'side.docs.cliInstall': 'CLI Install',
|
|
145
147
|
'side.docs.cliInstall.meta': 'Install / Update / Uninstall',
|
|
148
|
+
'side.update.available': 'Update available',
|
|
149
|
+
'side.update.availableWithVersion': 'Update available v{version}',
|
|
150
|
+
'side.update.meta': 'Open update command',
|
|
151
|
+
'side.update.metaVersions': 'Current v{current} → latest v{latest}',
|
|
152
|
+
'side.update.checkFailed': 'Failed to check latest version',
|
|
153
|
+
'side.update.check': 'Check for updates',
|
|
154
|
+
'side.update.checking': 'Checking for updates…',
|
|
155
|
+
'side.update.checkingMeta': 'Contacting npm registry',
|
|
156
|
+
'side.update.upToDate': 'Up to date',
|
|
157
|
+
'side.update.currentOnly': 'Current v{current}',
|
|
158
|
+
'side.update.retry': 'Retry version check',
|
|
146
159
|
'side.config.codex': 'Codex',
|
|
147
160
|
'side.config.codex.meta': 'Provider / Model',
|
|
148
161
|
'side.config.claude': 'Claude Code',
|
|
@@ -358,7 +371,7 @@ const en = Object.freeze({
|
|
|
358
371
|
'plugins.builtin.commentPolish.desc': 'Polish the following code comments {{code}}',
|
|
359
372
|
'plugins.builtin.commentPolish.line1': 'Polish the following code comments',
|
|
360
373
|
'plugins.builtin.ruleAck.name': 'Rule acknowledgement',
|
|
361
|
-
'plugins.builtin.ruleAck.desc': '
|
|
374
|
+
'plugins.builtin.ruleAck.desc': 'Generate rule acknowledgement reply',
|
|
362
375
|
'plugins.builtin.ruleAck.line1': 'Please follow 【{{rule}}】, reply when received',
|
|
363
376
|
|
|
364
377
|
// Toasts
|
|
@@ -385,6 +398,50 @@ const en = Object.freeze({
|
|
|
385
398
|
'toast.templates.nameRequired': 'Template name is required',
|
|
386
399
|
'toast.templates.builtinNotDuplicable': 'Built-in templates cannot be duplicated',
|
|
387
400
|
'toast.templates.builtinNotDeletable': 'Built-in templates cannot be deleted',
|
|
401
|
+
'toast.operation.success': 'Operation successful',
|
|
402
|
+
'toast.load.fail': 'Failed to load file',
|
|
403
|
+
'toast.apply.success': 'Configuration applied',
|
|
404
|
+
'toast.apply.fail': 'Failed to apply configuration',
|
|
405
|
+
'toast.check.success': 'Check passed',
|
|
406
|
+
'toast.check.fail': 'Check failed',
|
|
407
|
+
'toast.noChanges': 'No changes detected',
|
|
408
|
+
'toast.template.loadFail': 'Failed to load template',
|
|
409
|
+
'toast.template.empty': 'Template cannot be empty',
|
|
410
|
+
'toast.template.applied': 'Template applied',
|
|
411
|
+
'toast.template.appliedButRefreshFail': 'Template applied, but UI refresh failed. Please refresh manually',
|
|
412
|
+
'toast.template.applyFail': 'Failed to apply template',
|
|
413
|
+
'toast.provider.addFail': 'Failed to add',
|
|
414
|
+
'toast.provider.notDeletable': 'This provider is reserved and cannot be deleted',
|
|
415
|
+
'toast.provider.deletedAndSwitched': 'Provider deleted, auto-switched to {provider}{model}',
|
|
416
|
+
'toast.provider.notEditable': 'This provider is reserved and cannot be edited',
|
|
417
|
+
'toast.provider.updateFail': 'Failed to update',
|
|
418
|
+
'toast.provider.resetSuccess': 'Config reset{backup}',
|
|
419
|
+
'toast.provider.resetFail': 'Reset failed',
|
|
420
|
+
'toast.provider.fieldsRequired': 'Name, URL, API Key and model are required',
|
|
421
|
+
'toast.provider.urlRequired': 'URL is required',
|
|
422
|
+
'toast.claude.modelRequired': 'Please enter model',
|
|
423
|
+
'toast.claude.apiKeyRequired': 'Please configure API Key first',
|
|
424
|
+
'toast.claude.checkConfig': 'Please check Claude configuration',
|
|
425
|
+
'toast.claude.savedWithoutKey': 'Saved (API Key not filled)',
|
|
426
|
+
'toast.claude.applied': 'Claude config applied',
|
|
427
|
+
'toast.claude.exists': 'Config already exists',
|
|
428
|
+
'toast.claude.keepOne': 'Keep at least one',
|
|
429
|
+
'toast.claude.externalAuth': 'Using external auth, no API Key needed',
|
|
430
|
+
'toast.claude.balanceEnabled': 'Claude local load balancing enabled',
|
|
431
|
+
'toast.claude.balanceDisabled': 'Claude local load balancing disabled',
|
|
432
|
+
'toast.claude.balanceEnableFail': 'Failed to enable load balancing',
|
|
433
|
+
'toast.claude.balanceRequireProvider': 'Please add and configure at least one Claude provider',
|
|
434
|
+
'toast.claude.loadSettingsFail': 'Failed to load Claude settings',
|
|
435
|
+
'validation.claude.nameRequired': 'Config name is required',
|
|
436
|
+
'validation.claude.nameExists': 'Name already exists',
|
|
437
|
+
'validation.claude.apiKeyRequired': 'API Key is required',
|
|
438
|
+
'validation.claude.baseUrlRequired': 'Base URL is required',
|
|
439
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL only supports http/https',
|
|
440
|
+
'validation.claude.modelRequired': 'Model name is required',
|
|
441
|
+
'modal.claudeDelete.title': 'Delete Claude config',
|
|
442
|
+
'modal.claudeDelete.message': 'Delete config "{name}"?',
|
|
443
|
+
'modal.claudeDelete.confirm': 'Delete',
|
|
444
|
+
'modal.claudeDelete.cancel': 'Cancel',
|
|
388
445
|
'toast.templates.deleteTitle': 'Delete template',
|
|
389
446
|
'toast.templates.deleteMessage': 'Delete “{name}”? This action cannot be undone.',
|
|
390
447
|
'toast.templates.deleteConfirm': 'Delete',
|
|
@@ -1092,6 +1149,13 @@ const en = Object.freeze({
|
|
|
1092
1149
|
'claude.model': 'Model',
|
|
1093
1150
|
'claude.model.placeholder': 'e.g. claude-3-7-sonnet',
|
|
1094
1151
|
'claude.model.hint': 'Model changes are saved and applied to the current config automatically.',
|
|
1152
|
+
'claude.targetApi.label': 'Target API',
|
|
1153
|
+
'claude.targetApi.responses': 'Anthropic',
|
|
1154
|
+
'claude.targetApi.chatCompletions': 'OpenAI Chat Completions (/v1/chat/completions)',
|
|
1155
|
+
'claude.targetApi.ollama': 'Ollama Chat (/api/chat)',
|
|
1156
|
+
'claude.targetApi.chatCompletionsBadge': 'OpenAI Chat Completions',
|
|
1157
|
+
'claude.targetApi.ollamaBadge': 'Ollama',
|
|
1158
|
+
'claude.targetApi.hint': 'When Chat Completions or Ollama is selected, the Claude-compatible proxy performs the built-in conversion without changing the Codex provider wire_api; Ollama does not require an API key.',
|
|
1095
1159
|
'claude.health.title': 'Config health check',
|
|
1096
1160
|
'claude.health.run': 'Run check',
|
|
1097
1161
|
'claude.health.running': 'Checking...',
|
|
@@ -62,6 +62,8 @@ const ja = Object.freeze({
|
|
|
62
62
|
'common.notExistsWillCreateOnApply': '存在しません。適用時に作成されます',
|
|
63
63
|
'common.notExistsWillCreateOnSave': '存在しません。保存時に作成されます',
|
|
64
64
|
'common.none': 'なし',
|
|
65
|
+
'common.configured': '設定済み',
|
|
66
|
+
'common.notConfigured': '未設定',
|
|
65
67
|
'cli.missing.title': '{name} CLI がインストールされていません',
|
|
66
68
|
'cli.missing.subtitle': '{name} CLI をインストールしてからこのページをご利用ください。',
|
|
67
69
|
'cli.missing.openDocs': 'インストールガイドを開く',
|
|
@@ -144,6 +146,17 @@ const ja = Object.freeze({
|
|
|
144
146
|
'side.overview.doctor.meta': '概要 / 診断 / ジャンプ',
|
|
145
147
|
'side.docs.cliInstall': 'CLI インストール',
|
|
146
148
|
'side.docs.cliInstall.meta': 'インストール / 更新 / 削除',
|
|
149
|
+
'side.update.available': '新しいバージョンがあります',
|
|
150
|
+
'side.update.availableWithVersion': '新しいバージョン v{version}',
|
|
151
|
+
'side.update.meta': '更新コマンドを開く',
|
|
152
|
+
'side.update.metaVersions': '現在 v{current} → 最新 v{latest}',
|
|
153
|
+
'side.update.checkFailed': '最新バージョンの確認に失敗しました',
|
|
154
|
+
'side.update.check': '更新を確認',
|
|
155
|
+
'side.update.checking': '更新を確認中…',
|
|
156
|
+
'side.update.checkingMeta': 'npm registry に接続中',
|
|
157
|
+
'side.update.upToDate': '最新です',
|
|
158
|
+
'side.update.currentOnly': '現在 v{current}',
|
|
159
|
+
'side.update.retry': 'バージョン確認を再試行',
|
|
147
160
|
'side.config.codex': 'Codex',
|
|
148
161
|
'side.config.codex.meta': 'Provider / Model',
|
|
149
162
|
'side.config.claude': 'Claude Code',
|
|
@@ -360,7 +373,7 @@ const ja = Object.freeze({
|
|
|
360
373
|
'plugins.builtin.commentPolish.desc': '以下のコードコメントを軽く整えてください {{code}}',
|
|
361
374
|
'plugins.builtin.commentPolish.line1': '以下のコードコメントを軽く整えてください',
|
|
362
375
|
'plugins.builtin.ruleAck.name': 'ルール確認返信',
|
|
363
|
-
'plugins.builtin.ruleAck.desc': '
|
|
376
|
+
'plugins.builtin.ruleAck.desc': 'ルールに従うよう確認返信を指示',
|
|
364
377
|
'plugins.builtin.ruleAck.line1': '【{{rule}}】に従って、受信確認を返してください',
|
|
365
378
|
|
|
366
379
|
// Toasts
|
|
@@ -391,6 +404,50 @@ const ja = Object.freeze({
|
|
|
391
404
|
'toast.templates.deleteMessage': '「{name}」を削除しますか?この操作は取り消せません。',
|
|
392
405
|
'toast.templates.deleteConfirm': '削除',
|
|
393
406
|
'toast.templates.deleteCancel': 'キャンセル',
|
|
407
|
+
'toast.operation.success': '操作が成功しました',
|
|
408
|
+
'toast.load.fail': 'ファイルの読み込みに失敗しました',
|
|
409
|
+
'toast.apply.success': '設定が適用されました',
|
|
410
|
+
'toast.apply.fail': '設定の適用に失敗しました',
|
|
411
|
+
'toast.check.success': 'チェック成功',
|
|
412
|
+
'toast.check.fail': 'チェック失敗',
|
|
413
|
+
'toast.noChanges': '変更が検出されませんでした',
|
|
414
|
+
'toast.template.loadFail': 'テンプレートの読み込みに失敗しました',
|
|
415
|
+
'toast.template.empty': 'テンプレートは空にできません',
|
|
416
|
+
'toast.template.applied': 'テンプレートが適用されました',
|
|
417
|
+
'toast.template.appliedButRefreshFail': 'テンプレートは適用されましたが、UI の更新に失敗しました。手動で更新してください',
|
|
418
|
+
'toast.template.applyFail': 'テンプレートの適用に失敗しました',
|
|
419
|
+
'toast.provider.addFail': '追加に失敗しました',
|
|
420
|
+
'toast.provider.notDeletable': 'このプロバイダーは予約済みのため削除できません',
|
|
421
|
+
'toast.provider.deletedAndSwitched': 'プロバイダーを削除し、{provider}{model}に自動切り替えしました',
|
|
422
|
+
'toast.provider.notEditable': 'このプロバイダーは予約済みのため編集できません',
|
|
423
|
+
'toast.provider.updateFail': '更新に失敗しました',
|
|
424
|
+
'toast.provider.resetSuccess': '設定をリセットしました{backup}',
|
|
425
|
+
'toast.provider.resetFail': 'リセットに失敗しました',
|
|
426
|
+
'toast.provider.fieldsRequired': '名前、URL、API Key、モデル名は必須です',
|
|
427
|
+
'toast.provider.urlRequired': 'URL は必須です',
|
|
428
|
+
'toast.claude.modelRequired': 'モデルを入力してください',
|
|
429
|
+
'toast.claude.apiKeyRequired': '先に API Key を設定してください',
|
|
430
|
+
'toast.claude.checkConfig': 'Claude 設定を確認してください',
|
|
431
|
+
'toast.claude.savedWithoutKey': '保存しました(API Key 未入力)',
|
|
432
|
+
'toast.claude.applied': 'Claude 設定が適用されました',
|
|
433
|
+
'toast.claude.exists': '設定が既に存在します',
|
|
434
|
+
'toast.claude.keepOne': '最低1つは残してください',
|
|
435
|
+
'toast.claude.externalAuth': '外部認証を使用するため、API Key は不要です',
|
|
436
|
+
'toast.claude.balanceEnabled': 'Claude ローカル負荷分散が有効になりました',
|
|
437
|
+
'toast.claude.balanceDisabled': 'Claude ローカル負荷分散が無効になりました',
|
|
438
|
+
'toast.claude.balanceEnableFail': '負荷分散の有効化に失敗しました',
|
|
439
|
+
'toast.claude.balanceRequireProvider': '最低1つの Claude プロバイダーを追加・設定してください',
|
|
440
|
+
'toast.claude.loadSettingsFail': 'Claude settings の読み込みに失敗しました',
|
|
441
|
+
'validation.claude.nameRequired': '設定名は必須です',
|
|
442
|
+
'validation.claude.nameExists': '名前が既に存在します',
|
|
443
|
+
'validation.claude.apiKeyRequired': 'API Key は必須です',
|
|
444
|
+
'validation.claude.baseUrlRequired': 'Base URL は必須です',
|
|
445
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL は http/https のみサポートします',
|
|
446
|
+
'validation.claude.modelRequired': 'モデル名は必須です',
|
|
447
|
+
'modal.claudeDelete.title': 'Claude 設定の削除',
|
|
448
|
+
'modal.claudeDelete.message': '設定 "{name}" を削除しますか?',
|
|
449
|
+
'modal.claudeDelete.confirm': '削除',
|
|
450
|
+
'modal.claudeDelete.cancel': 'キャンセル',
|
|
394
451
|
|
|
395
452
|
// Basic modals
|
|
396
453
|
'modal.providerAdd.title': 'プロバイダー追加',
|
|
@@ -1085,6 +1142,13 @@ const ja = Object.freeze({
|
|
|
1085
1142
|
'claude.model': 'モデル',
|
|
1086
1143
|
'claude.model.placeholder': '例: claude-3-7-sonnet',
|
|
1087
1144
|
'claude.model.hint': 'モデル変更後は自動保存され、現在の設定に適用されます。',
|
|
1145
|
+
'claude.targetApi.label': 'ターゲット API',
|
|
1146
|
+
'claude.targetApi.responses': 'Anthropic',
|
|
1147
|
+
'claude.targetApi.chatCompletions': 'OpenAI Chat Completions (/v1/chat/completions)',
|
|
1148
|
+
'claude.targetApi.ollama': 'Ollama Chat (/api/chat)',
|
|
1149
|
+
'claude.targetApi.chatCompletionsBadge': 'OpenAI Chat Completions',
|
|
1150
|
+
'claude.targetApi.ollamaBadge': 'Ollama',
|
|
1151
|
+
'claude.targetApi.hint': 'Chat Completions または Ollama を選ぶと Claude 互換プロキシが内蔵変換します。Codex provider の wire_api は変更しません。Ollama では API Key は不要です。',
|
|
1088
1152
|
'claude.health.title': '設定ヘルスチェック',
|
|
1089
1153
|
'claude.health.run': 'チェック実行',
|
|
1090
1154
|
'claude.health.running': 'チェック中...',
|
|
@@ -6,7 +6,7 @@ const vi = Object.freeze({
|
|
|
6
6
|
'plugins.builtin.commentPolish.desc': 'Chỉnh nhẹ các chú thích mã sau {{code}}',
|
|
7
7
|
'plugins.builtin.commentPolish.line1': 'Chỉnh nhẹ các chú thích mã sau',
|
|
8
8
|
'plugins.builtin.ruleAck.name': 'Xác nhận quy tắc',
|
|
9
|
-
'plugins.builtin.ruleAck.desc': '
|
|
9
|
+
'plugins.builtin.ruleAck.desc': 'Tạo phản hồi xác nhận quy tắc',
|
|
10
10
|
'plugins.builtin.ruleAck.line1': 'Hãy làm theo【{{rule}}】, nhận được thì phản hồi',
|
|
11
11
|
// Global
|
|
12
12
|
'lang.zh': 'Tiếng Trung',
|
|
@@ -71,6 +71,8 @@ const vi = Object.freeze({
|
|
|
71
71
|
'common.notExistsWillCreateOnApply': 'Không tồn tại. Sẽ được tạo khi áp dụng.',
|
|
72
72
|
'common.notExistsWillCreateOnSave': 'Không tồn tại. Sẽ được tạo khi lưu.',
|
|
73
73
|
'common.none': 'Không có',
|
|
74
|
+
'common.configured': 'Đã cấu hình',
|
|
75
|
+
'common.notConfigured': 'Chưa cấu hình',
|
|
74
76
|
'common.notSelected': 'Chưa chọn',
|
|
75
77
|
|
|
76
78
|
// Roles / labels
|
|
@@ -104,6 +106,17 @@ const vi = Object.freeze({
|
|
|
104
106
|
'side.overview.doctor.meta': 'Tổng quan / Chẩn đoán',
|
|
105
107
|
'side.docs.cliInstall': 'Cài CLI',
|
|
106
108
|
'side.docs.cliInstall.meta': 'Cài đặt / Cập nhật / Gỡ',
|
|
109
|
+
'side.update.available': 'Có bản cập nhật',
|
|
110
|
+
'side.update.availableWithVersion': 'Có bản cập nhật v{version}',
|
|
111
|
+
'side.update.meta': 'Mở lệnh cập nhật',
|
|
112
|
+
'side.update.metaVersions': 'Hiện tại v{current} → mới nhất v{latest}',
|
|
113
|
+
'side.update.checkFailed': 'Không thể kiểm tra phiên bản mới nhất',
|
|
114
|
+
'side.update.check': 'Kiểm tra cập nhật',
|
|
115
|
+
'side.update.checking': 'Đang kiểm tra cập nhật…',
|
|
116
|
+
'side.update.checkingMeta': 'Đang kết nối npm registry',
|
|
117
|
+
'side.update.upToDate': 'Đã là phiên bản mới nhất',
|
|
118
|
+
'side.update.currentOnly': 'Hiện tại v{current}',
|
|
119
|
+
'side.update.retry': 'Thử kiểm tra phiên bản lại',
|
|
107
120
|
'side.config.codex': 'Codex',
|
|
108
121
|
'side.config.codex.meta': 'Provider / Model',
|
|
109
122
|
'side.config.claude': 'Claude Code',
|
|
@@ -233,7 +246,69 @@ const vi = Object.freeze({
|
|
|
233
246
|
'dashboard.doctor.title': 'Doctor',
|
|
234
247
|
'dashboard.doctor.runChecks': 'Chạy kiểm tra',
|
|
235
248
|
'dashboard.doctor.checking': 'Đang kiểm tra...',
|
|
236
|
-
'dashboard.doctor.export': 'Xuất báo cáo'
|
|
249
|
+
'dashboard.doctor.export': 'Xuất báo cáo',
|
|
250
|
+
|
|
251
|
+
// Claude target API
|
|
252
|
+
'claude.targetApi.label': 'API đích',
|
|
253
|
+
'claude.targetApi.responses': 'Anthropic',
|
|
254
|
+
'claude.targetApi.chatCompletions': 'OpenAI Chat Completions (/v1/chat/completions)',
|
|
255
|
+
'claude.targetApi.ollama': 'Ollama Chat (/api/chat)',
|
|
256
|
+
'claude.targetApi.chatCompletionsBadge': 'OpenAI Chat Completions',
|
|
257
|
+
'claude.targetApi.ollamaBadge': 'Ollama',
|
|
258
|
+
'claude.targetApi.hint': 'Khi chọn Chat Completions hoặc Ollama, proxy tương thích Claude sẽ chuyển đổi nội bộ mà không thay đổi wire_api của Codex provider; Ollama không cần API key.',
|
|
259
|
+
|
|
260
|
+
// Toasts
|
|
261
|
+
'toast.copy.empty': 'Không có gì để sao chép',
|
|
262
|
+
'toast.copy.ok': 'Đã sao chép',
|
|
263
|
+
'toast.copy.fail': 'Sao chép thất bại',
|
|
264
|
+
'toast.save.ok': 'Đã lưu',
|
|
265
|
+
'toast.save.fail': 'Lưu thất bại',
|
|
266
|
+
'toast.delete.ok': 'Đã xóa',
|
|
267
|
+
'toast.delete.fail': 'Xóa thất bại',
|
|
268
|
+
'toast.operation.success': 'Thao tác thành công',
|
|
269
|
+
'toast.load.fail': 'Tải tệp thất bại',
|
|
270
|
+
'toast.apply.success': 'Đã áp dụng cấu hình',
|
|
271
|
+
'toast.apply.fail': 'Áp dụng cấu hình thất bại',
|
|
272
|
+
'toast.check.success': 'Kiểm tra thành công',
|
|
273
|
+
'toast.check.fail': 'Kiểm tra thất bại',
|
|
274
|
+
'toast.noChanges': 'Không phát hiện thay đổi',
|
|
275
|
+
'toast.template.loadFail': 'Tải mẫu thất bại',
|
|
276
|
+
'toast.template.empty': 'Mẫu không được để trống',
|
|
277
|
+
'toast.template.applied': 'Đã áp dụng mẫu',
|
|
278
|
+
'toast.template.appliedButRefreshFail': 'Đã áp dụng mẫu, nhưng làm mới giao diện thất bại. Vui lòng làm mới thủ công',
|
|
279
|
+
'toast.template.applyFail': 'Áp dụng mẫu thất bại',
|
|
280
|
+
'toast.provider.addFail': 'Thêm thất bại',
|
|
281
|
+
'toast.provider.notDeletable': 'Provider này là mục dành riêng, không thể xóa',
|
|
282
|
+
'toast.provider.deletedAndSwitched': 'Đã xóa provider, tự động chuyển sang {provider}{model}',
|
|
283
|
+
'toast.provider.notEditable': 'Provider này là mục dành riêng, không thể chỉnh sửa',
|
|
284
|
+
'toast.provider.updateFail': 'Cập nhật thất bại',
|
|
285
|
+
'toast.provider.resetSuccess': 'Đã cài đặt lại cấu hình{backup}',
|
|
286
|
+
'toast.provider.resetFail': 'Cài đặt lại thất bại',
|
|
287
|
+
'toast.provider.fieldsRequired': 'Tên, URL, API Key và tên mô hình là bắt buộc',
|
|
288
|
+
'toast.provider.urlRequired': 'URL là bắt buộc',
|
|
289
|
+
'toast.claude.modelRequired': 'Vui lòng nhập mô hình',
|
|
290
|
+
'toast.claude.apiKeyRequired': 'Vui lòng cấu hình API Key trước',
|
|
291
|
+
'toast.claude.checkConfig': 'Vui lòng kiểm tra cấu hình Claude',
|
|
292
|
+
'toast.claude.savedWithoutKey': 'Đã lưu (chưa điền API Key)',
|
|
293
|
+
'toast.claude.applied': 'Cấu hình Claude đã được áp dụng',
|
|
294
|
+
'toast.claude.exists': 'Cấu hình đã tồn tại',
|
|
295
|
+
'toast.claude.keepOne': 'Giữ ít nhất một mục',
|
|
296
|
+
'toast.claude.externalAuth': 'Sử dụng xác thực bên ngoài, không cần API Key',
|
|
297
|
+
'toast.claude.balanceEnabled': 'Đã bật cân bằng tải cục bộ Claude',
|
|
298
|
+
'toast.claude.balanceDisabled': 'Đã tắt cân bằng tải cục bộ Claude',
|
|
299
|
+
'toast.claude.balanceEnableFail': 'Không thể bật cân bằng tải',
|
|
300
|
+
'toast.claude.balanceRequireProvider': 'Vui lòng thêm và cấu hình ít nhất một nhà cung cấp Claude',
|
|
301
|
+
'toast.claude.loadSettingsFail': 'Tải cài đặt Claude thất bại',
|
|
302
|
+
'validation.claude.nameRequired': 'Tên cấu hình là bắt buộc',
|
|
303
|
+
'validation.claude.nameExists': 'Tên đã tồn tại',
|
|
304
|
+
'validation.claude.apiKeyRequired': 'API Key là bắt buộc',
|
|
305
|
+
'validation.claude.baseUrlRequired': 'Base URL là bắt buộc',
|
|
306
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL chỉ hỗ trợ http/https',
|
|
307
|
+
'validation.claude.modelRequired': 'Tên mô hình là bắt buộc',
|
|
308
|
+
'modal.claudeDelete.title': 'Xóa cấu hình Claude',
|
|
309
|
+
'modal.claudeDelete.message': 'Xóa cấu hình "{name}"?',
|
|
310
|
+
'modal.claudeDelete.confirm': 'Xóa',
|
|
311
|
+
'modal.claudeDelete.cancel': 'Hủy',
|
|
237
312
|
});
|
|
238
313
|
|
|
239
314
|
export { vi };
|
|
@@ -61,6 +61,8 @@ const zh = Object.freeze({
|
|
|
61
61
|
'common.notExistsWillCreateOnApply': '不存在,将在应用时创建',
|
|
62
62
|
'common.notExistsWillCreateOnSave': '不存在,将在保存时创建',
|
|
63
63
|
'common.none': '暂无',
|
|
64
|
+
'common.configured': '已配置',
|
|
65
|
+
'common.notConfigured': '未配置',
|
|
64
66
|
'cli.missing.title': '{name} CLI 未安装',
|
|
65
67
|
'cli.missing.subtitle': '请先安装 {name} CLI 后再继续使用此页面。',
|
|
66
68
|
'cli.missing.openDocs': '打开安装指南',
|
|
@@ -143,6 +145,17 @@ const zh = Object.freeze({
|
|
|
143
145
|
'side.overview.doctor.meta': '总览 / 诊断 / 跳转',
|
|
144
146
|
'side.docs.cliInstall': 'CLI 安装',
|
|
145
147
|
'side.docs.cliInstall.meta': '安装 / 升级 / 卸载',
|
|
148
|
+
'side.update.available': '有新版本',
|
|
149
|
+
'side.update.availableWithVersion': '有新版本 v{version}',
|
|
150
|
+
'side.update.meta': '点击查看更新命令',
|
|
151
|
+
'side.update.metaVersions': '当前 v{current} → 最新 v{latest}',
|
|
152
|
+
'side.update.checkFailed': '检查最新版本失败',
|
|
153
|
+
'side.update.check': '检查更新',
|
|
154
|
+
'side.update.checking': '正在检查更新…',
|
|
155
|
+
'side.update.checkingMeta': '正在连接 npm registry',
|
|
156
|
+
'side.update.upToDate': '已是最新',
|
|
157
|
+
'side.update.currentOnly': '当前 v{current}',
|
|
158
|
+
'side.update.retry': '重试版本检查',
|
|
146
159
|
'side.config.codex': 'Codex',
|
|
147
160
|
'side.config.codex.meta': 'Provider / Model',
|
|
148
161
|
'side.config.claude': 'Claude Code',
|
|
@@ -358,7 +371,7 @@ const zh = Object.freeze({
|
|
|
358
371
|
'plugins.builtin.commentPolish.desc': '轻微收敛以下代码注释 {{code}}',
|
|
359
372
|
'plugins.builtin.commentPolish.line1': '轻微收敛以下代码注释',
|
|
360
373
|
'plugins.builtin.ruleAck.name': '规则确认回复',
|
|
361
|
-
'plugins.builtin.ruleAck.desc': '
|
|
374
|
+
'plugins.builtin.ruleAck.desc': '生成规则确认回复',
|
|
362
375
|
'plugins.builtin.ruleAck.line1': '请根据【{{rule}}】,收到请回复',
|
|
363
376
|
|
|
364
377
|
// Toasts
|
|
@@ -386,9 +399,53 @@ const zh = Object.freeze({
|
|
|
386
399
|
'toast.templates.builtinNotDuplicable': '内置模板不可复制',
|
|
387
400
|
'toast.templates.builtinNotDeletable': '内置模板不可删除',
|
|
388
401
|
'toast.templates.deleteTitle': '删除模板',
|
|
389
|
-
'toast.templates.deleteMessage': '
|
|
402
|
+
'toast.templates.deleteMessage': '删除”{name}”?此操作无法撤销。',
|
|
390
403
|
'toast.templates.deleteConfirm': '删除',
|
|
391
404
|
'toast.templates.deleteCancel': '取消',
|
|
405
|
+
'toast.operation.success': '操作成功',
|
|
406
|
+
'toast.load.fail': '加载文件失败',
|
|
407
|
+
'toast.apply.success': '配置已应用',
|
|
408
|
+
'toast.apply.fail': '应用配置失败',
|
|
409
|
+
'toast.check.success': '检查通过',
|
|
410
|
+
'toast.check.fail': '检查失败',
|
|
411
|
+
'toast.noChanges': '未检测到改动',
|
|
412
|
+
'toast.template.loadFail': '加载模板失败',
|
|
413
|
+
'toast.template.empty': '模板不能为空',
|
|
414
|
+
'toast.template.applied': '模板已应用',
|
|
415
|
+
'toast.template.appliedButRefreshFail': '模板已应用,但界面刷新失败,请手动刷新',
|
|
416
|
+
'toast.template.applyFail': '应用模板失败',
|
|
417
|
+
'toast.provider.addFail': '添加失败',
|
|
418
|
+
'toast.provider.notDeletable': '该 provider 为保留项,不可删除',
|
|
419
|
+
'toast.provider.deletedAndSwitched': '已删除提供商,自动切换到 {provider}{model}',
|
|
420
|
+
'toast.provider.notEditable': '该 provider 为保留项,不可编辑',
|
|
421
|
+
'toast.provider.updateFail': '更新失败',
|
|
422
|
+
'toast.provider.resetSuccess': '配置已重装{backup}',
|
|
423
|
+
'toast.provider.resetFail': '重装失败',
|
|
424
|
+
'toast.provider.fieldsRequired': '名称、URL、API Key 和模型名称必填',
|
|
425
|
+
'toast.provider.urlRequired': 'URL 必填',
|
|
426
|
+
'toast.claude.modelRequired': '请输入模型',
|
|
427
|
+
'toast.claude.apiKeyRequired': '请先配置 API Key',
|
|
428
|
+
'toast.claude.checkConfig': '请检查 Claude 配置',
|
|
429
|
+
'toast.claude.savedWithoutKey': '已保存(未填写 API Key)',
|
|
430
|
+
'toast.claude.applied': 'Claude 配置已生效',
|
|
431
|
+
'toast.claude.exists': '配置已存在',
|
|
432
|
+
'toast.claude.keepOne': '至少保留一项',
|
|
433
|
+
'toast.claude.externalAuth': '使用外部认证,无需 API Key',
|
|
434
|
+
'toast.claude.balanceEnabled': 'Claude 本地负载均衡已启用',
|
|
435
|
+
'toast.claude.balanceDisabled': 'Claude 本地负载均衡已关闭',
|
|
436
|
+
'toast.claude.balanceEnableFail': '启用本地负载均衡失败',
|
|
437
|
+
'toast.claude.balanceRequireProvider': '请先添加并配置至少一个 Claude 提供商',
|
|
438
|
+
'toast.claude.loadSettingsFail': '加载 Claude settings 失败',
|
|
439
|
+
'validation.claude.nameRequired': '配置名称不能为空',
|
|
440
|
+
'validation.claude.nameExists': '名称已存在',
|
|
441
|
+
'validation.claude.apiKeyRequired': 'API Key 必填',
|
|
442
|
+
'validation.claude.baseUrlRequired': 'Base URL 必填',
|
|
443
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL 仅支持 http/https',
|
|
444
|
+
'validation.claude.modelRequired': '模型名称必填',
|
|
445
|
+
'modal.claudeDelete.title': '删除 Claude 配置',
|
|
446
|
+
'modal.claudeDelete.message': '确定删除配置 "{name}"?',
|
|
447
|
+
'modal.claudeDelete.confirm': '删除',
|
|
448
|
+
'modal.claudeDelete.cancel': '取消',
|
|
392
449
|
|
|
393
450
|
// Basic modals
|
|
394
451
|
'modal.providerAdd.title': '添加提供商',
|
|
@@ -1095,6 +1152,13 @@ const zh = Object.freeze({
|
|
|
1095
1152
|
'claude.model': '模型',
|
|
1096
1153
|
'claude.model.placeholder': '例如: claude-3-7-sonnet',
|
|
1097
1154
|
'claude.model.hint': '模型修改后会自动保存并应用到当前配置。',
|
|
1155
|
+
'claude.targetApi.label': '目标 API',
|
|
1156
|
+
'claude.targetApi.responses': 'Anthropic',
|
|
1157
|
+
'claude.targetApi.chatCompletions': 'OpenAI Chat Completions (/v1/chat/completions)',
|
|
1158
|
+
'claude.targetApi.ollama': 'Ollama Chat (/api/chat)',
|
|
1159
|
+
'claude.targetApi.chatCompletionsBadge': 'OpenAI Chat Completions',
|
|
1160
|
+
'claude.targetApi.ollamaBadge': 'Ollama',
|
|
1161
|
+
'claude.targetApi.hint': '选择 Chat Completions 或 Ollama 时由 Claude 兼容代理内建转换,不修改 Codex provider 的 wire_api;Ollama 可不填 API Key。',
|
|
1098
1162
|
'claude.health.title': '配置健康检查',
|
|
1099
1163
|
'claude.health.run': '运行检查',
|
|
1100
1164
|
'claude.health.running': '检查中...',
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
<div id="app" class="container" v-cloak>
|
|
2
|
+
<div v-if="!sessionStandalone" class="mobile-brand-bar">
|
|
3
|
+
<div class="mobile-brand-title">Codex Mate<span v-if="appVersion" class="brand-version"> v{{ appVersion }}</span></div>
|
|
4
|
+
<button
|
|
5
|
+
v-if="isAppVersionStatusVisible()"
|
|
6
|
+
type="button"
|
|
7
|
+
:class="['mobile-update-chip', 'mobile-update-chip--' + appVersionStatusKind()]"
|
|
8
|
+
:title="appVersionStatusTitle()"
|
|
9
|
+
@click="handleAppVersionStatusClick">
|
|
10
|
+
<span class="side-update-dot"></span>
|
|
11
|
+
<span class="mobile-update-text">{{ appUpdateNoticeText() }}</span>
|
|
12
|
+
</button>
|
|
13
|
+
</div>
|
|
2
14
|
<div v-if="!sessionStandalone" class="top-tabs" role="tablist" :aria-label="t('nav.topTabs.aria')">
|
|
3
15
|
<button type="button" class="top-tab"
|
|
4
16
|
id="tab-dashboard"
|
|
@@ -110,6 +122,18 @@
|
|
|
110
122
|
<div class="brand-kicker">Codex Mate<span v-if="appVersion" class="brand-version"> v{{ appVersion }}</span></div>
|
|
111
123
|
</div>
|
|
112
124
|
</div>
|
|
125
|
+
<button
|
|
126
|
+
v-if="isAppVersionStatusVisible()"
|
|
127
|
+
type="button"
|
|
128
|
+
:class="['side-update-notice', 'side-update-notice--' + appVersionStatusKind()]"
|
|
129
|
+
:title="appVersionStatusTitle()"
|
|
130
|
+
@click="handleAppVersionStatusClick">
|
|
131
|
+
<span class="side-update-dot"></span>
|
|
132
|
+
<span class="side-update-copy">
|
|
133
|
+
<span class="side-update-title">{{ appUpdateNoticeText() }}</span>
|
|
134
|
+
<span class="side-update-meta">{{ appUpdateNoticeMeta() }}</span>
|
|
135
|
+
</span>
|
|
136
|
+
</button>
|
|
113
137
|
</div>
|
|
114
138
|
|
|
115
139
|
<div class="side-rail-nav">
|
|
@@ -165,6 +165,15 @@
|
|
|
165
165
|
<input v-model="newClaudeConfig.model" :class="['form-input', { invalid: !!claudeConfigFieldError('add', 'model') }]" :placeholder="t('placeholder.modelExample')" autocomplete="off" spellcheck="false">
|
|
166
166
|
<div v-if="claudeConfigFieldError('add', 'model')" class="form-hint form-error">{{ claudeConfigFieldError('add', 'model') }}</div>
|
|
167
167
|
</div>
|
|
168
|
+
<div class="form-group">
|
|
169
|
+
<label class="form-label">{{ t('claude.targetApi.label') }}</label>
|
|
170
|
+
<select v-model="newClaudeConfig.targetApi" class="form-input">
|
|
171
|
+
<option value="responses">{{ t('claude.targetApi.responses') }}</option>
|
|
172
|
+
<option value="chat_completions">{{ t('claude.targetApi.chatCompletions') }}</option>
|
|
173
|
+
<option value="ollama">{{ t('claude.targetApi.ollama') }}</option>
|
|
174
|
+
</select>
|
|
175
|
+
<div class="form-hint">{{ t('claude.targetApi.hint') }}</div>
|
|
176
|
+
</div>
|
|
168
177
|
|
|
169
178
|
<div class="btn-group">
|
|
170
179
|
<button class="btn btn-cancel" @click="closeClaudeConfigModal">{{ t('common.cancel') }}</button>
|
|
@@ -204,6 +213,15 @@
|
|
|
204
213
|
<input v-model="editingConfig.model" :class="['form-input', { invalid: !!claudeConfigFieldError('edit', 'model') }]" :placeholder="t('placeholder.modelExample')" autocomplete="off" spellcheck="false">
|
|
205
214
|
<div v-if="claudeConfigFieldError('edit', 'model')" class="form-hint form-error">{{ claudeConfigFieldError('edit', 'model') }}</div>
|
|
206
215
|
</div>
|
|
216
|
+
<div class="form-group">
|
|
217
|
+
<label class="form-label">{{ t('claude.targetApi.label') }}</label>
|
|
218
|
+
<select v-model="editingConfig.targetApi" class="form-input">
|
|
219
|
+
<option value="responses">{{ t('claude.targetApi.responses') }}</option>
|
|
220
|
+
<option value="chat_completions">{{ t('claude.targetApi.chatCompletions') }}</option>
|
|
221
|
+
<option value="ollama">{{ t('claude.targetApi.ollama') }}</option>
|
|
222
|
+
</select>
|
|
223
|
+
<div class="form-hint">{{ t('claude.targetApi.hint') }}</div>
|
|
224
|
+
</div>
|
|
207
225
|
|
|
208
226
|
<div class="btn-group">
|
|
209
227
|
<button class="btn btn-cancel" @click="closeEditConfigModal">{{ t('common.cancel') }}</button>
|
|
@@ -260,4 +278,3 @@
|
|
|
260
278
|
</div>
|
|
261
279
|
</div>
|
|
262
280
|
</div>
|
|
263
|
-
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
<label class="settings-toggle-row tool-config-write-toggle">
|
|
35
35
|
<input
|
|
36
36
|
type="checkbox"
|
|
37
|
+
autocomplete="off"
|
|
37
38
|
:checked="isToolConfigWriteAllowed('claude')"
|
|
38
39
|
:disabled="toolConfigPermissionSaving.claude"
|
|
39
40
|
@change="setToolConfigPermission('claude', $event.target.checked)">
|
|
@@ -145,16 +146,18 @@
|
|
|
145
146
|
</div>
|
|
146
147
|
<div v-for="(config, name) in claudeConfigs" :key="name" :class="['card', { active: currentClaudeConfig === name }]" @click="applyClaudeConfig(name)" @keydown.enter.self.prevent="applyClaudeConfig(name)" @keydown.space.self.prevent="applyClaudeConfig(name)" tabindex="0" role="button" :aria-current="currentClaudeConfig === name ? 'true' : null">
|
|
147
148
|
<div class="card-leading">
|
|
148
|
-
<div class="card-icon">{{ name.charAt(0).toUpperCase() }}
|
|
149
|
+
<div class="card-icon">{{ name.charAt(0).toUpperCase() }}<span v-if="config.targetApi === 'chat_completions' || config.targetApi === 'ollama'" class="card-icon-dot" :title="t('config.transformProvider.title')"></span></div>
|
|
149
150
|
<div class="card-content">
|
|
150
151
|
<div class="card-title">{{ name }}</div>
|
|
151
152
|
<div class="card-subtitle card-subtitle-model">{{ config.model || t('claude.model.unset') }}</div>
|
|
153
|
+
<div class="card-subtitle" v-if="config.targetApi === 'chat_completions'">{{ t('claude.targetApi.chatCompletionsBadge') }}</div>
|
|
154
|
+
<div class="card-subtitle" v-else-if="config.targetApi === 'ollama'">{{ t('claude.targetApi.ollamaBadge') }}</div>
|
|
152
155
|
<div class="card-subtitle card-subtitle-url" v-if="config.baseUrl">{{ config.baseUrl }}</div>
|
|
153
156
|
</div>
|
|
154
157
|
</div>
|
|
155
158
|
<div class="card-trailing">
|
|
156
159
|
<span v-if="claudeSpeedResults[name]" :class="['latency', claudeSpeedResults[name].ok ? 'ok' : 'error']">{{ formatLatency(claudeSpeedResults[name]) }}</span>
|
|
157
|
-
<span :class="['pill', config.hasKey ? 'configured' : 'empty']">{{ config.hasKey ? t('
|
|
160
|
+
<span :class="['pill', config.hasKey ? 'configured' : 'empty']">{{ config.hasKey ? t('common.configured') : t('common.notConfigured') }}</span>
|
|
158
161
|
<div class="card-actions" @click.stop>
|
|
159
162
|
<button class="card-action-btn" @click="openEditConfigModal(name)" :aria-label="t('claude.action.editAria', { name })" :title="t('claude.action.edit')">
|
|
160
163
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
<label class="settings-toggle-row tool-config-write-toggle">
|
|
35
35
|
<input
|
|
36
36
|
type="checkbox"
|
|
37
|
+
autocomplete="off"
|
|
37
38
|
:checked="isToolConfigWriteAllowed('codex')"
|
|
38
39
|
:disabled="toolConfigPermissionSaving.codex"
|
|
39
40
|
@change="setToolConfigPermission('codex', $event.target.checked)">
|
|
@@ -203,4 +204,4 @@
|
|
|
203
204
|
</div>
|
|
204
205
|
</div>
|
|
205
206
|
</template>
|
|
206
|
-
</div>
|
|
207
|
+
</div>
|