codexmate 0.0.42 → 0.0.43
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/cli.js +3 -2
- package/package.json +2 -2
- package/web-ui/app.js +18 -8
- package/web-ui/modules/app.methods.agents.mjs +6 -6
- package/web-ui/modules/app.methods.claude-config.mjs +37 -37
- package/web-ui/modules/app.methods.codex-config.mjs +10 -10
- 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 +18 -18
- package/web-ui/modules/app.methods.startup-claude.mjs +3 -0
- package/web-ui/modules/app.methods.tool-config-permissions.mjs +3 -0
- package/web-ui/modules/i18n/locales/en.mjs +47 -1
- package/web-ui/modules/i18n/locales/ja.mjs +47 -1
- package/web-ui/modules/i18n/locales/vi.mjs +57 -2
- package/web-ui/modules/i18n/locales/zh.mjs +48 -2
- package/web-ui/partials/index/panel-config-claude.html +1 -1
- package/web-ui/res/web-ui-render.precompiled.js +1 -1
- package/web-ui/styles/titles-cards.css +10 -4
package/cli.js
CHANGED
|
@@ -10461,6 +10461,7 @@ function assertRequestAuthorized(req, res) {
|
|
|
10461
10461
|
|
|
10462
10462
|
function isProtectedWebSurfacePath(requestPath) {
|
|
10463
10463
|
return requestPath === '/'
|
|
10464
|
+
|| requestPath === '/session'
|
|
10464
10465
|
|| requestPath === '/web-ui/index.html'
|
|
10465
10466
|
|| requestPath.startsWith('/web-ui/')
|
|
10466
10467
|
|| requestPath.startsWith('/res/');
|
|
@@ -11889,8 +11890,8 @@ function createWebServer({ htmlPath, assetsDir, webDir, host, port, openBrowser
|
|
|
11889
11890
|
});
|
|
11890
11891
|
fs.createReadStream(filePath).pipe(res);
|
|
11891
11892
|
} else {
|
|
11892
|
-
//
|
|
11893
|
-
if (requestPath === '/') {
|
|
11893
|
+
// Serve the SPA shell for routable entry points. Keep /web-ui as 404.
|
|
11894
|
+
if (requestPath === '/' || requestPath === '/session') {
|
|
11894
11895
|
try {
|
|
11895
11896
|
const html = readBundledWebUiHtml(htmlPath);
|
|
11896
11897
|
res.writeHead(200, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexmate",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.43",
|
|
4
4
|
"description": "Codex/Claude Code/OpenClaw 配置、会话与任务编排 CLI + Web 工具",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@iarna/toml": "^2.2.5",
|
|
49
|
-
"@vue/compiler-dom": "^3.5.30",
|
|
50
49
|
"json5": "^2.2.3",
|
|
51
50
|
"yauzl": "^3.2.1",
|
|
52
51
|
"zip-lib": "^1.2.1"
|
|
@@ -72,6 +71,7 @@
|
|
|
72
71
|
"author": "ymkiux",
|
|
73
72
|
"license": "Apache-2.0",
|
|
74
73
|
"devDependencies": {
|
|
74
|
+
"@vue/compiler-dom": "^3.5.30",
|
|
75
75
|
"vitepress": "^1.6.4"
|
|
76
76
|
}
|
|
77
77
|
}
|
package/web-ui/app.js
CHANGED
|
@@ -366,7 +366,21 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
366
366
|
codexDownloadProgress: 0,
|
|
367
367
|
codexDownloadTimer: null,
|
|
368
368
|
settingsTab: 'general',
|
|
369
|
-
toolConfigPermissions: {
|
|
369
|
+
toolConfigPermissions: (function() {
|
|
370
|
+
try {
|
|
371
|
+
const cached = localStorage.getItem('toolConfigPermissions');
|
|
372
|
+
if (cached) {
|
|
373
|
+
const parsed = JSON.parse(cached);
|
|
374
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
375
|
+
return {
|
|
376
|
+
codex: parsed.codex === true,
|
|
377
|
+
claude: parsed.claude === true
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
} catch (_) {}
|
|
382
|
+
return { codex: false, claude: false };
|
|
383
|
+
})(),
|
|
370
384
|
toolConfigPermissionSaving: { codex: false, claude: false },
|
|
371
385
|
sessionTrashEnabled: true,
|
|
372
386
|
sessionTrashItems: [],
|
|
@@ -445,13 +459,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
445
459
|
window.location.replace(url.toString());
|
|
446
460
|
return;
|
|
447
461
|
}
|
|
448
|
-
//
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
url.search = '';
|
|
452
|
-
url.hash = '';
|
|
453
|
-
window.history.replaceState(null, '', url.toString());
|
|
454
|
-
}
|
|
462
|
+
// Do not strip query/hash during startup: /session uses them to identify the
|
|
463
|
+
// standalone session, and shareable tab/filter URLs are consumed below before
|
|
464
|
+
// later runtime canonicalization can clean the address bar.
|
|
455
465
|
} catch (_) {}
|
|
456
466
|
|
|
457
467
|
if (typeof this.initI18n === 'function') {
|
|
@@ -60,7 +60,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
60
60
|
if (!isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
this.showMessage('
|
|
63
|
+
this.showMessage(this.t('toast.load.fail'), 'error');
|
|
64
64
|
} finally {
|
|
65
65
|
if (isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
66
66
|
this.agentsLoading = false;
|
|
@@ -92,7 +92,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
92
92
|
if (!isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
this.showMessage('
|
|
95
|
+
this.showMessage(this.t('toast.load.fail'), 'error');
|
|
96
96
|
} finally {
|
|
97
97
|
if (isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
98
98
|
this.agentsLoading = false;
|
|
@@ -127,7 +127,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
127
127
|
if (!isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
-
this.showMessage('
|
|
130
|
+
this.showMessage(this.t('toast.load.fail'), 'error');
|
|
131
131
|
} finally {
|
|
132
132
|
if (isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
133
133
|
this.agentsLoading = false;
|
|
@@ -171,7 +171,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
171
171
|
if (!isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
174
|
-
this.showMessage('
|
|
174
|
+
this.showMessage(this.t('toast.load.fail'), 'error');
|
|
175
175
|
} finally {
|
|
176
176
|
if (isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
177
177
|
this.agentsLoading = false;
|
|
@@ -588,7 +588,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
588
588
|
}
|
|
589
589
|
if (!this.agentsDiffVisible) {
|
|
590
590
|
if (!this.hasAgentsContentChanged()) {
|
|
591
|
-
this.showMessage('
|
|
591
|
+
this.showMessage(this.t('toast.noChanges'), 'info');
|
|
592
592
|
return;
|
|
593
593
|
}
|
|
594
594
|
await this.prepareAgentsDiff();
|
|
@@ -642,7 +642,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
642
642
|
this.showMessage(successLabel, 'success');
|
|
643
643
|
this.closeAgentsModal({ force: true });
|
|
644
644
|
} catch (e) {
|
|
645
|
-
this.showMessage('
|
|
645
|
+
this.showMessage(this.t('toast.save.fail'), 'error');
|
|
646
646
|
} finally {
|
|
647
647
|
this.agentsSaving = false;
|
|
648
648
|
}
|
|
@@ -31,23 +31,23 @@ function getClaudeConfigValidationForContext(vm, mode = 'add') {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
if (!name) {
|
|
34
|
-
errors.name = '
|
|
34
|
+
errors.name = vm.t('validation.claude.nameRequired');
|
|
35
35
|
} else if (mode === 'add' && vm.claudeConfigs && vm.claudeConfigs[name]) {
|
|
36
|
-
errors.name = '
|
|
36
|
+
errors.name = vm.t('validation.claude.nameExists');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (!apiKey && !externalCredentialType) {
|
|
40
|
-
errors.apiKey = '
|
|
40
|
+
errors.apiKey = vm.t('validation.claude.apiKeyRequired');
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
if (!baseUrl) {
|
|
44
|
-
errors.baseUrl = '
|
|
44
|
+
errors.baseUrl = vm.t('validation.claude.baseUrlRequired');
|
|
45
45
|
} else if (!isValidClaudeHttpUrl(baseUrl)) {
|
|
46
|
-
errors.baseUrl = '
|
|
46
|
+
errors.baseUrl = vm.t('validation.claude.baseUrlHttpOnly');
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (!model) {
|
|
50
|
-
errors.model = '
|
|
50
|
+
errors.model = vm.t('validation.claude.modelRequired');
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return {
|
|
@@ -79,7 +79,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
79
79
|
}
|
|
80
80
|
const model = (this.currentClaudeModel || '').trim();
|
|
81
81
|
if (!model) {
|
|
82
|
-
this.showMessage('
|
|
82
|
+
this.showMessage(this.t('toast.claude.modelRequired'), 'error');
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
const existing = this.claudeConfigs[name] || {};
|
|
@@ -89,7 +89,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
89
89
|
this.saveClaudeConfigs();
|
|
90
90
|
this.updateClaudeModelsCurrent();
|
|
91
91
|
if (!this.claudeConfigs[name].apiKey && !this.claudeConfigs[name].externalCredentialType) {
|
|
92
|
-
this.showMessage('
|
|
92
|
+
this.showMessage(this.t('toast.claude.apiKeyRequired'), 'error');
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
this.applyClaudeConfig(name);
|
|
@@ -153,7 +153,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
153
153
|
updateConfig() {
|
|
154
154
|
const validation = getClaudeConfigValidationForContext(this, 'edit');
|
|
155
155
|
if (!validation.ok) {
|
|
156
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
156
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
157
157
|
}
|
|
158
158
|
const name = validation.name;
|
|
159
159
|
this.editingConfig.apiKey = validation.apiKey;
|
|
@@ -161,7 +161,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
161
161
|
this.editingConfig.model = validation.model;
|
|
162
162
|
this.claudeConfigs[name] = this.mergeClaudeConfig(this.claudeConfigs[name], this.editingConfig);
|
|
163
163
|
this.saveClaudeConfigs();
|
|
164
|
-
this.showMessage('
|
|
164
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
165
165
|
this.closeEditConfigModal();
|
|
166
166
|
if (name === this.currentClaudeConfig) {
|
|
167
167
|
this.refreshClaudeModelContext();
|
|
@@ -181,7 +181,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
181
181
|
async saveAndApplyConfig() {
|
|
182
182
|
const validation = getClaudeConfigValidationForContext(this, 'edit');
|
|
183
183
|
if (!validation.ok) {
|
|
184
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
184
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
185
185
|
}
|
|
186
186
|
const name = validation.name;
|
|
187
187
|
this.editingConfig.apiKey = validation.apiKey;
|
|
@@ -192,7 +192,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
192
192
|
|
|
193
193
|
const config = this.claudeConfigs[name];
|
|
194
194
|
if (!config.apiKey) {
|
|
195
|
-
this.showMessage('
|
|
195
|
+
this.showMessage(this.t('toast.claude.savedWithoutKey'), 'info');
|
|
196
196
|
this.closeEditConfigModal();
|
|
197
197
|
if (name === this.currentClaudeConfig) {
|
|
198
198
|
this.refreshClaudeModelContext();
|
|
@@ -204,25 +204,25 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
204
204
|
try {
|
|
205
205
|
const res = await api('apply-claude-config', { config });
|
|
206
206
|
if (res.error || res.success === false) {
|
|
207
|
-
this.showMessage(res.error || '
|
|
207
|
+
this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
208
208
|
} else {
|
|
209
209
|
this.currentClaudeConfig = name;
|
|
210
210
|
if (this._lastAppliedClaudeKey !== _claudeKey) {
|
|
211
|
-
this.showMessage('
|
|
211
|
+
this.showMessage(this.t('toast.claude.applied'), 'success');
|
|
212
212
|
this._lastAppliedClaudeKey = _claudeKey;
|
|
213
213
|
}
|
|
214
214
|
this.closeEditConfigModal();
|
|
215
215
|
this.refreshClaudeModelContext();
|
|
216
216
|
}
|
|
217
217
|
} catch (_) {
|
|
218
|
-
this.showMessage('
|
|
218
|
+
this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
219
219
|
}
|
|
220
220
|
},
|
|
221
221
|
|
|
222
222
|
addClaudeConfig() {
|
|
223
223
|
const validation = getClaudeConfigValidationForContext(this, 'add');
|
|
224
224
|
if (!validation.ok) {
|
|
225
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
225
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
226
226
|
}
|
|
227
227
|
this.newClaudeConfig.name = validation.name;
|
|
228
228
|
this.newClaudeConfig.apiKey = validation.apiKey;
|
|
@@ -231,27 +231,27 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
231
231
|
const name = validation.name;
|
|
232
232
|
const duplicateName = this.findDuplicateClaudeConfigName(this.newClaudeConfig);
|
|
233
233
|
if (duplicateName) {
|
|
234
|
-
return this.showMessage('
|
|
234
|
+
return this.showMessage(this.t('toast.claude.exists'), 'info');
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
this.claudeConfigs[name] = this.mergeClaudeConfig({}, this.newClaudeConfig);
|
|
238
238
|
|
|
239
239
|
this.currentClaudeConfig = name;
|
|
240
240
|
this.saveClaudeConfigs();
|
|
241
|
-
this.showMessage('
|
|
241
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
242
242
|
this.closeClaudeConfigModal();
|
|
243
243
|
this.refreshClaudeModelContext();
|
|
244
244
|
},
|
|
245
245
|
|
|
246
246
|
async deleteClaudeConfig(name) {
|
|
247
247
|
if (Object.keys(this.claudeConfigs).length <= 1) {
|
|
248
|
-
return this.showMessage('
|
|
248
|
+
return this.showMessage(this.t('toast.claude.keepOne'), 'error');
|
|
249
249
|
}
|
|
250
250
|
const confirmed = await this.requestConfirmDialog({
|
|
251
|
-
title: '
|
|
252
|
-
message:
|
|
253
|
-
confirmText: '
|
|
254
|
-
cancelText: '
|
|
251
|
+
title: this.t('modal.claudeDelete.title'),
|
|
252
|
+
message: this.t('modal.claudeDelete.message', { name }),
|
|
253
|
+
confirmText: this.t('modal.claudeDelete.confirm'),
|
|
254
|
+
cancelText: this.t('modal.claudeDelete.cancel'),
|
|
255
255
|
danger: true
|
|
256
256
|
});
|
|
257
257
|
if (!confirmed) return;
|
|
@@ -261,7 +261,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
261
261
|
this.currentClaudeConfig = Object.keys(this.claudeConfigs)[0];
|
|
262
262
|
}
|
|
263
263
|
this.saveClaudeConfigs();
|
|
264
|
-
this.showMessage('
|
|
264
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
265
265
|
this.refreshClaudeModelContext();
|
|
266
266
|
},
|
|
267
267
|
|
|
@@ -273,24 +273,24 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
273
273
|
|
|
274
274
|
if (!config.apiKey) {
|
|
275
275
|
if (config.externalCredentialType) {
|
|
276
|
-
return this.showMessage('
|
|
276
|
+
return this.showMessage(this.t('toast.claude.externalAuth'), 'info');
|
|
277
277
|
}
|
|
278
|
-
return this.showMessage('
|
|
278
|
+
return this.showMessage(this.t('toast.claude.apiKeyRequired'), 'error');
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
const _claudeKey2 = `${name}|${config.apiKey || ""}|${config.baseUrl || ""}|${config.model || ""}`;
|
|
282
282
|
try {
|
|
283
283
|
const res = await api('apply-claude-config', { config });
|
|
284
284
|
if (res.error || res.success === false) {
|
|
285
|
-
this.showMessage(res.error || '
|
|
285
|
+
this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
286
286
|
} else {
|
|
287
287
|
if (this._lastAppliedClaudeKey !== _claudeKey2) {
|
|
288
|
-
this.showMessage('
|
|
288
|
+
this.showMessage(this.t('toast.apply.success'), 'success');
|
|
289
289
|
this._lastAppliedClaudeKey = _claudeKey2;
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
} catch (_) {
|
|
293
|
-
this.showMessage('
|
|
293
|
+
this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
294
294
|
}
|
|
295
295
|
},
|
|
296
296
|
|
|
@@ -328,12 +328,12 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
330
|
if (enable) {
|
|
331
|
-
this.showMessage('
|
|
331
|
+
this.showMessage(this.t('toast.claude.balanceEnabled'), 'success');
|
|
332
332
|
} else {
|
|
333
|
-
this.showMessage('
|
|
333
|
+
this.showMessage(this.t('toast.claude.balanceDisabled'), 'success');
|
|
334
334
|
}
|
|
335
335
|
} catch (e) {
|
|
336
|
-
this.showMessage('
|
|
336
|
+
this.showMessage(this.t('toast.operation.fail'), 'error');
|
|
337
337
|
}
|
|
338
338
|
},
|
|
339
339
|
|
|
@@ -379,18 +379,18 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
379
379
|
|
|
380
380
|
const candidates = this.claudeLocalBridgeCandidateProviders();
|
|
381
381
|
if (candidates.length === 0) {
|
|
382
|
-
return this.showMessage('
|
|
382
|
+
return this.showMessage(this.t('toast.claude.balanceRequireProvider'), 'error');
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
try {
|
|
386
386
|
const res = await api('claude-local-bridge-toggle', { enable: true });
|
|
387
387
|
if (res.error) {
|
|
388
|
-
this.showMessage(res.error || '
|
|
388
|
+
this.showMessage(res.error || this.t('toast.claude.balanceEnableFail'), 'error');
|
|
389
389
|
return;
|
|
390
390
|
}
|
|
391
|
-
this.showMessage('
|
|
391
|
+
this.showMessage(this.t('toast.claude.balanceEnabled'), 'success');
|
|
392
392
|
} catch (e) {
|
|
393
|
-
this.showMessage('
|
|
393
|
+
this.showMessage(this.t('toast.claude.balanceEnableFail'), 'error');
|
|
394
394
|
}
|
|
395
395
|
},
|
|
396
396
|
|
|
@@ -405,7 +405,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
405
405
|
this.configTemplateContext = 'claude';
|
|
406
406
|
this.showConfigTemplateModal = true;
|
|
407
407
|
} catch (e) {
|
|
408
|
-
this.showMessage('
|
|
408
|
+
this.showMessage(this.t('toast.claude.loadSettingsFail'), 'error');
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
};
|
|
@@ -66,7 +66,7 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
66
66
|
const maxLabel = res.maxMessages === 'all' ? 'all' : res.maxMessages;
|
|
67
67
|
this.showMessage(`会话导出完成(已截断:最多 ${maxLabel} 条消息)`, 'info');
|
|
68
68
|
} else {
|
|
69
|
-
this.showMessage('
|
|
69
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
70
70
|
}
|
|
71
71
|
} catch (e) {
|
|
72
72
|
this.showMessage('导出失败', 'error');
|
|
@@ -325,7 +325,7 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
325
325
|
if (hasResponseError(res)) {
|
|
326
326
|
this.healthCheckResult = null;
|
|
327
327
|
if (!silent) {
|
|
328
|
-
this.showMessage(getResponseMessage(res, '
|
|
328
|
+
this.showMessage(getResponseMessage(res, this.t('toast.check.fail')), 'error');
|
|
329
329
|
}
|
|
330
330
|
return;
|
|
331
331
|
}
|
|
@@ -342,13 +342,13 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
342
342
|
this.healthCheckBatchDone = total;
|
|
343
343
|
this.healthCheckBatchFailed = errors + warns;
|
|
344
344
|
if (!silent && res.ok) {
|
|
345
|
-
this.showMessage('
|
|
345
|
+
this.showMessage(this.t('toast.check.success'), 'success');
|
|
346
346
|
}
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
349
349
|
this.healthCheckResult = null;
|
|
350
350
|
if (!silent) {
|
|
351
|
-
this.showMessage('
|
|
351
|
+
this.showMessage(this.t('toast.check.fail'), 'error');
|
|
352
352
|
}
|
|
353
353
|
return;
|
|
354
354
|
}
|
|
@@ -473,7 +473,7 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
473
473
|
} else {
|
|
474
474
|
this.healthCheckResult = null;
|
|
475
475
|
if (!silent) {
|
|
476
|
-
this.showMessage('
|
|
476
|
+
this.showMessage(this.t('toast.check.fail'), 'error');
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
} catch (e) {
|
|
@@ -561,7 +561,7 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
561
561
|
this.configTemplateContext = 'codex';
|
|
562
562
|
this.showConfigTemplateModal = true;
|
|
563
563
|
} catch (e) {
|
|
564
|
-
this.showMessage('
|
|
564
|
+
this.showMessage(this.t('toast.template.loadFail'), 'error');
|
|
565
565
|
}
|
|
566
566
|
},
|
|
567
567
|
|
|
@@ -797,7 +797,7 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
797
797
|
return;
|
|
798
798
|
}
|
|
799
799
|
if (!this.configTemplateContent || !this.configTemplateContent.trim()) {
|
|
800
|
-
this.showMessage('
|
|
800
|
+
this.showMessage(this.t('toast.template.empty'), 'error');
|
|
801
801
|
return;
|
|
802
802
|
}
|
|
803
803
|
|
|
@@ -822,15 +822,15 @@ export function createCodexConfigMethods(options = {}) {
|
|
|
822
822
|
this.showMessage(res.error, 'error');
|
|
823
823
|
return;
|
|
824
824
|
}
|
|
825
|
-
this.showMessage('
|
|
825
|
+
this.showMessage(this.t('toast.template.applied'), 'success');
|
|
826
826
|
this.closeConfigTemplateModal({ force: true });
|
|
827
827
|
try {
|
|
828
828
|
await this.loadAll();
|
|
829
829
|
} catch (_) {
|
|
830
|
-
this.showMessage('
|
|
830
|
+
this.showMessage(this.t('toast.template.appliedButRefreshFail'), 'error');
|
|
831
831
|
}
|
|
832
832
|
} catch (e) {
|
|
833
|
-
this.showMessage('
|
|
833
|
+
this.showMessage(this.t('toast.template.applyFail'), 'error');
|
|
834
834
|
} finally {
|
|
835
835
|
this.configTemplateApplying = false;
|
|
836
836
|
}
|
|
@@ -274,7 +274,7 @@ export function createOpenclawPersistMethods(options = {}) {
|
|
|
274
274
|
try {
|
|
275
275
|
const name = this.persistOpenclawConfig();
|
|
276
276
|
if (!name) return;
|
|
277
|
-
this.showMessage('
|
|
277
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
278
278
|
} finally {
|
|
279
279
|
this.openclawSaving = false;
|
|
280
280
|
}
|
|
@@ -170,7 +170,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
170
170
|
normalizeProviderDraftState(this.newProvider);
|
|
171
171
|
const validation = getProviderValidationForContext(this, 'add');
|
|
172
172
|
if (!validation.ok) {
|
|
173
|
-
return this.showMessage(validation.errors.name || validation.errors.url || validation.errors.key || validation.errors.model || '
|
|
173
|
+
return this.showMessage(validation.errors.name || validation.errors.url || validation.errors.key || validation.errors.model || this.t('toast.provider.fieldsRequired'), 'error');
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
try {
|
|
@@ -206,7 +206,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
206
206
|
};
|
|
207
207
|
this.providersList = [...this.providersList, newProvider];
|
|
208
208
|
|
|
209
|
-
this.showMessage('
|
|
209
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
210
210
|
this.closeAddModal();
|
|
211
211
|
|
|
212
212
|
if (suggestedModel) {
|
|
@@ -214,7 +214,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
214
214
|
this.currentModels[validation.name] = suggestedModel;
|
|
215
215
|
}
|
|
216
216
|
} catch (e) {
|
|
217
|
-
this.showMessage('
|
|
217
|
+
this.showMessage(this.t('toast.provider.addFail'), 'error');
|
|
218
218
|
}
|
|
219
219
|
},
|
|
220
220
|
|
|
@@ -275,7 +275,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
275
275
|
|
|
276
276
|
async deleteProvider(name) {
|
|
277
277
|
if (this.isNonDeletableProvider(name)) {
|
|
278
|
-
this.showMessage('
|
|
278
|
+
this.showMessage(this.t('toast.provider.notDeletable'), 'info');
|
|
279
279
|
return;
|
|
280
280
|
}
|
|
281
281
|
try {
|
|
@@ -301,12 +301,13 @@ export function createProvidersMethods(options = {}) {
|
|
|
301
301
|
...p,
|
|
302
302
|
current: p.name === res.provider
|
|
303
303
|
}));
|
|
304
|
-
|
|
304
|
+
const modelSuffix = res.model ? ` / ${res.model}` : '';
|
|
305
|
+
this.showMessage(this.t('toast.provider.deletedAndSwitched', { provider: res.provider, model: modelSuffix }), 'success');
|
|
305
306
|
} else {
|
|
306
|
-
this.showMessage('
|
|
307
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
307
308
|
}
|
|
308
309
|
} catch (_) {
|
|
309
|
-
this.showMessage('
|
|
310
|
+
this.showMessage(this.t('toast.delete.fail'), 'error');
|
|
310
311
|
}
|
|
311
312
|
},
|
|
312
313
|
|
|
@@ -330,7 +331,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
330
331
|
const requestId = Symbol('openEditModal');
|
|
331
332
|
this._openEditModalRequestId = requestId;
|
|
332
333
|
if (!this.shouldShowProviderEdit(provider)) {
|
|
333
|
-
this.showMessage('
|
|
334
|
+
this.showMessage(this.t('toast.provider.notEditable'), 'info');
|
|
334
335
|
return;
|
|
335
336
|
}
|
|
336
337
|
const isTransformProvider = (() => {
|
|
@@ -398,14 +399,14 @@ export function createProvidersMethods(options = {}) {
|
|
|
398
399
|
|
|
399
400
|
async updateProvider() {
|
|
400
401
|
if (this.editingProvider.readOnly || this.editingProvider.nonEditable) {
|
|
401
|
-
this.showMessage('
|
|
402
|
+
this.showMessage(this.t('toast.provider.notEditable'), 'error');
|
|
402
403
|
this.closeEditModal();
|
|
403
404
|
return;
|
|
404
405
|
}
|
|
405
406
|
normalizeProviderDraftState(this.editingProvider);
|
|
406
407
|
const validation = getProviderValidationForContext(this, 'edit');
|
|
407
408
|
if (!validation.ok) {
|
|
408
|
-
return this.showMessage(validation.errors.name || validation.errors.url || '
|
|
409
|
+
return this.showMessage(validation.errors.name || validation.errors.url || this.t('toast.provider.urlRequired'), 'error');
|
|
409
410
|
}
|
|
410
411
|
|
|
411
412
|
const params = { name: validation.name, url: validation.url };
|
|
@@ -441,9 +442,9 @@ export function createProvidersMethods(options = {}) {
|
|
|
441
442
|
});
|
|
442
443
|
|
|
443
444
|
this.closeEditModal();
|
|
444
|
-
this.showMessage('
|
|
445
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
445
446
|
} catch (e) {
|
|
446
|
-
this.showMessage('
|
|
447
|
+
this.showMessage(this.t('toast.provider.updateFail'), 'error');
|
|
447
448
|
}
|
|
448
449
|
},
|
|
449
450
|
|
|
@@ -469,10 +470,10 @@ export function createProvidersMethods(options = {}) {
|
|
|
469
470
|
return;
|
|
470
471
|
}
|
|
471
472
|
const backup = res.backupFile ? `(已备份: ${res.backupFile})` : '';
|
|
472
|
-
this.showMessage(
|
|
473
|
+
this.showMessage(this.t('toast.provider.resetSuccess', { backup }), 'success');
|
|
473
474
|
await this.loadAll();
|
|
474
475
|
} catch (e) {
|
|
475
|
-
this.showMessage('
|
|
476
|
+
this.showMessage(this.t('toast.provider.resetFail'), 'error');
|
|
476
477
|
} finally {
|
|
477
478
|
this.resetConfigLoading = false;
|
|
478
479
|
}
|
|
@@ -501,7 +502,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
501
502
|
}
|
|
502
503
|
return p;
|
|
503
504
|
});
|
|
504
|
-
this.showMessage('
|
|
505
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
505
506
|
this.closeModelModal();
|
|
506
507
|
}
|
|
507
508
|
} catch (_) {
|
|
@@ -525,7 +526,7 @@ export function createProvidersMethods(options = {}) {
|
|
|
525
526
|
}
|
|
526
527
|
return p;
|
|
527
528
|
});
|
|
528
|
-
this.showMessage('
|
|
529
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
529
530
|
}
|
|
530
531
|
} catch (_) {
|
|
531
532
|
this.showMessage('删除模型失败', 'error');
|
|
@@ -4,21 +4,21 @@ import {
|
|
|
4
4
|
} from '../logic.mjs';
|
|
5
5
|
|
|
6
6
|
const UI_MESSAGE_KEY_BY_TEXT = Object.freeze({
|
|
7
|
-
'操作成功': 'toast.
|
|
8
|
-
'操作失败': 'toast.
|
|
9
|
-
'添加失败': 'toast.
|
|
10
|
-
'更新失败': 'toast.
|
|
11
|
-
'删除失败': 'toast.
|
|
12
|
-
'已删除': 'toast.
|
|
13
|
-
'已复制': 'toast.
|
|
14
|
-
'复制失败': 'toast.
|
|
7
|
+
'操作成功': 'toast.operation.success',
|
|
8
|
+
'操作失败': 'toast.operation.fail',
|
|
9
|
+
'添加失败': 'toast.provider.addFail',
|
|
10
|
+
'更新失败': 'toast.provider.updateFail',
|
|
11
|
+
'删除失败': 'toast.delete.fail',
|
|
12
|
+
'已删除': 'toast.delete.ok',
|
|
13
|
+
'已复制': 'toast.copy.ok',
|
|
14
|
+
'复制失败': 'toast.copy.fail',
|
|
15
15
|
'剪贴板为空': 'toast.clipboardEmpty',
|
|
16
16
|
'无法读取剪贴板': 'toast.clipboardReadFailed',
|
|
17
17
|
'已粘贴': 'toast.pasted',
|
|
18
18
|
'未检测到改动': 'toast.noChanges',
|
|
19
|
-
'配置已应用': 'toast.
|
|
20
|
-
'应用配置失败': 'toast.
|
|
21
|
-
'应用失败': 'toast.
|
|
19
|
+
'配置已应用': 'toast.apply.success',
|
|
20
|
+
'应用配置失败': 'toast.apply.fail',
|
|
21
|
+
'应用失败': 'toast.apply.fail',
|
|
22
22
|
'配置已加载': 'toast.configLoaded',
|
|
23
23
|
'配置就绪': 'toast.configReady',
|
|
24
24
|
'加载配置失败': 'toast.loadConfigFailed',
|
|
@@ -26,12 +26,12 @@ const UI_MESSAGE_KEY_BY_TEXT = Object.freeze({
|
|
|
26
26
|
'读取配置超时': 'toast.readConfigTimeout',
|
|
27
27
|
'备份失败': 'toast.backupFailed',
|
|
28
28
|
'备份成功,开始下载': 'toast.backupReadyDownload',
|
|
29
|
-
'导入失败': 'toast.
|
|
30
|
-
'导入成功': 'toast.
|
|
29
|
+
'导入失败': 'toast.import.fail',
|
|
30
|
+
'导入成功': 'toast.import.ok',
|
|
31
31
|
'导入 skill 失败': 'toast.importSkillFailed',
|
|
32
|
-
'导出失败': 'toast.
|
|
33
|
-
'保存失败': 'toast.
|
|
34
|
-
'加载文件失败': 'toast.
|
|
32
|
+
'导出失败': 'toast.export.fail',
|
|
33
|
+
'保存失败': 'toast.save.fail',
|
|
34
|
+
'加载文件失败': 'toast.load.fail',
|
|
35
35
|
'请填写名称': 'toast.nameRequired',
|
|
36
36
|
'请输入名称': 'toast.nameRequired',
|
|
37
37
|
'名称已存在': 'toast.nameExists',
|
|
@@ -45,8 +45,8 @@ const UI_MESSAGE_KEY_BY_TEXT = Object.freeze({
|
|
|
45
45
|
'不可分享': 'toast.notShareable',
|
|
46
46
|
'已移入回收站': 'toast.movedToTrash',
|
|
47
47
|
'生成命令失败': 'toast.commandGenerationFailed',
|
|
48
|
-
'没有可复制内容': 'toast.
|
|
49
|
-
'没有可导出内容': 'toast.
|
|
48
|
+
'没有可复制内容': 'toast.copy.empty',
|
|
49
|
+
'没有可导出内容': 'toast.export.empty',
|
|
50
50
|
'会话已恢复': 'toast.sessionRestored',
|
|
51
51
|
'恢复失败': 'toast.restoreFailed',
|
|
52
52
|
'已彻底删除': 'toast.purged',
|
|
@@ -66,16 +66,22 @@ const UI_MESSAGE_PREFIX_ENTRIES = Object.freeze(
|
|
|
66
66
|
Object.entries(UI_MESSAGE_KEY_BY_TEXT).sort((a, b) => b[0].length - a[0].length)
|
|
67
67
|
);
|
|
68
68
|
|
|
69
|
-
function translateUiMessage(context, text) {
|
|
69
|
+
export function translateUiMessage(context, text) {
|
|
70
70
|
if (!context || typeof context.t !== 'function' || typeof text !== 'string') return text;
|
|
71
|
+
const translateKey = (key) => {
|
|
72
|
+
const translated = context.t(key);
|
|
73
|
+
return typeof translated === 'string' && translated && translated !== key ? translated : '';
|
|
74
|
+
};
|
|
71
75
|
const exactKey = UI_MESSAGE_KEY_BY_TEXT[text];
|
|
72
|
-
if (exactKey) return
|
|
76
|
+
if (exactKey) return translateKey(exactKey) || text;
|
|
73
77
|
const prefixEntry = UI_MESSAGE_PREFIX_ENTRIES.find(([sourceText]) => {
|
|
74
78
|
return text.length > sourceText.length && text.startsWith(sourceText);
|
|
75
79
|
});
|
|
76
80
|
if (!prefixEntry) return text;
|
|
77
81
|
const [sourceText, key] = prefixEntry;
|
|
78
|
-
|
|
82
|
+
const translatedPrefix = translateKey(key);
|
|
83
|
+
if (!translatedPrefix) return text;
|
|
84
|
+
return `${translatedPrefix}${text.slice(sourceText.length)}`;
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
function clearProgressResetTimer(context, timerKey) {
|
|
@@ -126,7 +126,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
} catch (_) {}
|
|
129
|
-
this.showMessage('
|
|
129
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
130
130
|
},
|
|
131
131
|
|
|
132
132
|
getSessionFilePath(session) {
|
|
@@ -152,7 +152,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
} catch (_) {}
|
|
155
|
-
this.showMessage('
|
|
155
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
156
156
|
},
|
|
157
157
|
|
|
158
158
|
getSessionExportKey(session) {
|
|
@@ -312,15 +312,15 @@ export function createSessionActionMethods(options = {}) {
|
|
|
312
312
|
copyAgentsContent() {
|
|
313
313
|
const text = typeof this.agentsContent === 'string' ? this.agentsContent : '';
|
|
314
314
|
if (!text) {
|
|
315
|
-
this.showMessage('
|
|
315
|
+
this.showMessage(this.t('toast.copy.empty'), 'info');
|
|
316
316
|
return;
|
|
317
317
|
}
|
|
318
318
|
const ok = this.fallbackCopyText(text);
|
|
319
319
|
if (ok) {
|
|
320
|
-
this.showMessage('
|
|
320
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
321
321
|
return;
|
|
322
322
|
}
|
|
323
|
-
this.showMessage('
|
|
323
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
324
324
|
},
|
|
325
325
|
|
|
326
326
|
exportAgentsContent() {
|
|
@@ -344,7 +344,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
344
344
|
async copyInstallCommand(cmd) {
|
|
345
345
|
const text = typeof cmd === 'string' ? cmd.trim() : '';
|
|
346
346
|
if (!text) {
|
|
347
|
-
this.showMessage('
|
|
347
|
+
this.showMessage(this.t('toast.copy.empty'), 'info');
|
|
348
348
|
return;
|
|
349
349
|
}
|
|
350
350
|
try {
|
|
@@ -359,7 +359,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
359
359
|
this.showMessage('已复制命令', 'success');
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
|
-
this.showMessage('
|
|
362
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
363
363
|
},
|
|
364
364
|
|
|
365
365
|
async copyResumeCommand(session) {
|
|
@@ -370,17 +370,17 @@ export function createSessionActionMethods(options = {}) {
|
|
|
370
370
|
const command = this.buildResumeCommand(session);
|
|
371
371
|
const ok = this.fallbackCopyText(command);
|
|
372
372
|
if (ok) {
|
|
373
|
-
this.showMessage('
|
|
373
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
374
374
|
return;
|
|
375
375
|
}
|
|
376
376
|
try {
|
|
377
377
|
if (navigator.clipboard && window.isSecureContext) {
|
|
378
378
|
await navigator.clipboard.writeText(command);
|
|
379
|
-
this.showMessage('
|
|
379
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
380
380
|
return;
|
|
381
381
|
}
|
|
382
382
|
} catch (_) {}
|
|
383
|
-
this.showMessage('
|
|
383
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
384
384
|
},
|
|
385
385
|
|
|
386
386
|
buildProviderShareCommand(payload) {
|
|
@@ -446,17 +446,17 @@ export function createSessionActionMethods(options = {}) {
|
|
|
446
446
|
}
|
|
447
447
|
const ok = this.fallbackCopyText(command);
|
|
448
448
|
if (ok) {
|
|
449
|
-
this.showMessage('
|
|
449
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
450
450
|
return;
|
|
451
451
|
}
|
|
452
452
|
try {
|
|
453
453
|
if (navigator.clipboard && window.isSecureContext) {
|
|
454
454
|
await navigator.clipboard.writeText(command);
|
|
455
|
-
this.showMessage('
|
|
455
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
456
456
|
return;
|
|
457
457
|
}
|
|
458
458
|
} catch (_) {}
|
|
459
|
-
this.showMessage('
|
|
459
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
460
460
|
} catch (_) {
|
|
461
461
|
this.showMessage('生成命令失败', 'error');
|
|
462
462
|
} finally {
|
|
@@ -485,17 +485,17 @@ export function createSessionActionMethods(options = {}) {
|
|
|
485
485
|
}
|
|
486
486
|
const ok = this.fallbackCopyText(command);
|
|
487
487
|
if (ok) {
|
|
488
|
-
this.showMessage('
|
|
488
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
489
489
|
return;
|
|
490
490
|
}
|
|
491
491
|
try {
|
|
492
492
|
if (navigator.clipboard && window.isSecureContext) {
|
|
493
493
|
await navigator.clipboard.writeText(command);
|
|
494
|
-
this.showMessage('
|
|
494
|
+
this.showMessage(this.t('toast.copy.ok'), 'success');
|
|
495
495
|
return;
|
|
496
496
|
}
|
|
497
497
|
} catch (_) {}
|
|
498
|
-
this.showMessage('
|
|
498
|
+
this.showMessage(this.t('toast.copy.fail'), 'error');
|
|
499
499
|
} catch (_) {
|
|
500
500
|
this.showMessage('生成命令失败', 'error');
|
|
501
501
|
} finally {
|
|
@@ -524,7 +524,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
524
524
|
return;
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
-
this.showMessage('
|
|
527
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
528
528
|
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
529
529
|
this.invalidateSessionsUsageData({ preserveList: true });
|
|
530
530
|
}
|
|
@@ -608,7 +608,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
608
608
|
// The delete already succeeded remotely; keep the success result.
|
|
609
609
|
}
|
|
610
610
|
} catch (_) {
|
|
611
|
-
this.showMessage('
|
|
611
|
+
this.showMessage(this.t('toast.delete.fail'), 'error');
|
|
612
612
|
} finally {
|
|
613
613
|
this.sessionDeleting[key] = false;
|
|
614
614
|
}
|
|
@@ -125,6 +125,9 @@ export function createStartupClaudeMethods(options = {}) {
|
|
|
125
125
|
codex: statusRes.toolConfigPermissions.codex === true,
|
|
126
126
|
claude: statusRes.toolConfigPermissions.claude === true
|
|
127
127
|
};
|
|
128
|
+
try {
|
|
129
|
+
localStorage.setItem('toolConfigPermissions', JSON.stringify(this.toolConfigPermissions));
|
|
130
|
+
} catch (_) {}
|
|
128
131
|
}
|
|
129
132
|
this.providersList = listRes.providers;
|
|
130
133
|
if (typeof this.loadLocalBridgeExcluded === 'function') { this.loadLocalBridgeExcluded(); }
|
|
@@ -64,6 +64,9 @@ export function createToolConfigPermissionMethods(options = {}) {
|
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
this.toolConfigPermissions = normalizePermissions(res && res.permissions);
|
|
67
|
+
try {
|
|
68
|
+
localStorage.setItem('toolConfigPermissions', JSON.stringify(this.toolConfigPermissions));
|
|
69
|
+
} catch (_) {}
|
|
67
70
|
this.showMessage(
|
|
68
71
|
nextAllowWrite
|
|
69
72
|
? this.t('toolConfig.allowToast')
|
|
@@ -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',
|
|
@@ -358,7 +360,7 @@ const en = Object.freeze({
|
|
|
358
360
|
'plugins.builtin.commentPolish.desc': 'Polish the following code comments {{code}}',
|
|
359
361
|
'plugins.builtin.commentPolish.line1': 'Polish the following code comments',
|
|
360
362
|
'plugins.builtin.ruleAck.name': 'Rule acknowledgement',
|
|
361
|
-
'plugins.builtin.ruleAck.desc': '
|
|
363
|
+
'plugins.builtin.ruleAck.desc': 'Generate rule acknowledgement reply',
|
|
362
364
|
'plugins.builtin.ruleAck.line1': 'Please follow 【{{rule}}】, reply when received',
|
|
363
365
|
|
|
364
366
|
// Toasts
|
|
@@ -385,6 +387,50 @@ const en = Object.freeze({
|
|
|
385
387
|
'toast.templates.nameRequired': 'Template name is required',
|
|
386
388
|
'toast.templates.builtinNotDuplicable': 'Built-in templates cannot be duplicated',
|
|
387
389
|
'toast.templates.builtinNotDeletable': 'Built-in templates cannot be deleted',
|
|
390
|
+
'toast.operation.success': 'Operation successful',
|
|
391
|
+
'toast.load.fail': 'Failed to load file',
|
|
392
|
+
'toast.apply.success': 'Configuration applied',
|
|
393
|
+
'toast.apply.fail': 'Failed to apply configuration',
|
|
394
|
+
'toast.check.success': 'Check passed',
|
|
395
|
+
'toast.check.fail': 'Check failed',
|
|
396
|
+
'toast.noChanges': 'No changes detected',
|
|
397
|
+
'toast.template.loadFail': 'Failed to load template',
|
|
398
|
+
'toast.template.empty': 'Template cannot be empty',
|
|
399
|
+
'toast.template.applied': 'Template applied',
|
|
400
|
+
'toast.template.appliedButRefreshFail': 'Template applied, but UI refresh failed. Please refresh manually',
|
|
401
|
+
'toast.template.applyFail': 'Failed to apply template',
|
|
402
|
+
'toast.provider.addFail': 'Failed to add',
|
|
403
|
+
'toast.provider.notDeletable': 'This provider is reserved and cannot be deleted',
|
|
404
|
+
'toast.provider.deletedAndSwitched': 'Provider deleted, auto-switched to {provider}{model}',
|
|
405
|
+
'toast.provider.notEditable': 'This provider is reserved and cannot be edited',
|
|
406
|
+
'toast.provider.updateFail': 'Failed to update',
|
|
407
|
+
'toast.provider.resetSuccess': 'Config reset{backup}',
|
|
408
|
+
'toast.provider.resetFail': 'Reset failed',
|
|
409
|
+
'toast.provider.fieldsRequired': 'Name, URL, API Key and model are required',
|
|
410
|
+
'toast.provider.urlRequired': 'URL is required',
|
|
411
|
+
'toast.claude.modelRequired': 'Please enter model',
|
|
412
|
+
'toast.claude.apiKeyRequired': 'Please configure API Key first',
|
|
413
|
+
'toast.claude.checkConfig': 'Please check Claude configuration',
|
|
414
|
+
'toast.claude.savedWithoutKey': 'Saved (API Key not filled)',
|
|
415
|
+
'toast.claude.applied': 'Claude config applied',
|
|
416
|
+
'toast.claude.exists': 'Config already exists',
|
|
417
|
+
'toast.claude.keepOne': 'Keep at least one',
|
|
418
|
+
'toast.claude.externalAuth': 'Using external auth, no API Key needed',
|
|
419
|
+
'toast.claude.balanceEnabled': 'Claude local load balancing enabled',
|
|
420
|
+
'toast.claude.balanceDisabled': 'Claude local load balancing disabled',
|
|
421
|
+
'toast.claude.balanceEnableFail': 'Failed to enable load balancing',
|
|
422
|
+
'toast.claude.balanceRequireProvider': 'Please add and configure at least one Claude provider',
|
|
423
|
+
'toast.claude.loadSettingsFail': 'Failed to load Claude settings',
|
|
424
|
+
'validation.claude.nameRequired': 'Config name is required',
|
|
425
|
+
'validation.claude.nameExists': 'Name already exists',
|
|
426
|
+
'validation.claude.apiKeyRequired': 'API Key is required',
|
|
427
|
+
'validation.claude.baseUrlRequired': 'Base URL is required',
|
|
428
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL only supports http/https',
|
|
429
|
+
'validation.claude.modelRequired': 'Model name is required',
|
|
430
|
+
'modal.claudeDelete.title': 'Delete Claude config',
|
|
431
|
+
'modal.claudeDelete.message': 'Delete config "{name}"?',
|
|
432
|
+
'modal.claudeDelete.confirm': 'Delete',
|
|
433
|
+
'modal.claudeDelete.cancel': 'Cancel',
|
|
388
434
|
'toast.templates.deleteTitle': 'Delete template',
|
|
389
435
|
'toast.templates.deleteMessage': 'Delete “{name}”? This action cannot be undone.',
|
|
390
436
|
'toast.templates.deleteConfirm': 'Delete',
|
|
@@ -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': 'インストールガイドを開く',
|
|
@@ -360,7 +362,7 @@ const ja = Object.freeze({
|
|
|
360
362
|
'plugins.builtin.commentPolish.desc': '以下のコードコメントを軽く整えてください {{code}}',
|
|
361
363
|
'plugins.builtin.commentPolish.line1': '以下のコードコメントを軽く整えてください',
|
|
362
364
|
'plugins.builtin.ruleAck.name': 'ルール確認返信',
|
|
363
|
-
'plugins.builtin.ruleAck.desc': '
|
|
365
|
+
'plugins.builtin.ruleAck.desc': 'ルールに従うよう確認返信を指示',
|
|
364
366
|
'plugins.builtin.ruleAck.line1': '【{{rule}}】に従って、受信確認を返してください',
|
|
365
367
|
|
|
366
368
|
// Toasts
|
|
@@ -391,6 +393,50 @@ const ja = Object.freeze({
|
|
|
391
393
|
'toast.templates.deleteMessage': '「{name}」を削除しますか?この操作は取り消せません。',
|
|
392
394
|
'toast.templates.deleteConfirm': '削除',
|
|
393
395
|
'toast.templates.deleteCancel': 'キャンセル',
|
|
396
|
+
'toast.operation.success': '操作が成功しました',
|
|
397
|
+
'toast.load.fail': 'ファイルの読み込みに失敗しました',
|
|
398
|
+
'toast.apply.success': '設定が適用されました',
|
|
399
|
+
'toast.apply.fail': '設定の適用に失敗しました',
|
|
400
|
+
'toast.check.success': 'チェック成功',
|
|
401
|
+
'toast.check.fail': 'チェック失敗',
|
|
402
|
+
'toast.noChanges': '変更が検出されませんでした',
|
|
403
|
+
'toast.template.loadFail': 'テンプレートの読み込みに失敗しました',
|
|
404
|
+
'toast.template.empty': 'テンプレートは空にできません',
|
|
405
|
+
'toast.template.applied': 'テンプレートが適用されました',
|
|
406
|
+
'toast.template.appliedButRefreshFail': 'テンプレートは適用されましたが、UI の更新に失敗しました。手動で更新してください',
|
|
407
|
+
'toast.template.applyFail': 'テンプレートの適用に失敗しました',
|
|
408
|
+
'toast.provider.addFail': '追加に失敗しました',
|
|
409
|
+
'toast.provider.notDeletable': 'このプロバイダーは予約済みのため削除できません',
|
|
410
|
+
'toast.provider.deletedAndSwitched': 'プロバイダーを削除し、{provider}{model}に自動切り替えしました',
|
|
411
|
+
'toast.provider.notEditable': 'このプロバイダーは予約済みのため編集できません',
|
|
412
|
+
'toast.provider.updateFail': '更新に失敗しました',
|
|
413
|
+
'toast.provider.resetSuccess': '設定をリセットしました{backup}',
|
|
414
|
+
'toast.provider.resetFail': 'リセットに失敗しました',
|
|
415
|
+
'toast.provider.fieldsRequired': '名前、URL、API Key、モデル名は必須です',
|
|
416
|
+
'toast.provider.urlRequired': 'URL は必須です',
|
|
417
|
+
'toast.claude.modelRequired': 'モデルを入力してください',
|
|
418
|
+
'toast.claude.apiKeyRequired': '先に API Key を設定してください',
|
|
419
|
+
'toast.claude.checkConfig': 'Claude 設定を確認してください',
|
|
420
|
+
'toast.claude.savedWithoutKey': '保存しました(API Key 未入力)',
|
|
421
|
+
'toast.claude.applied': 'Claude 設定が適用されました',
|
|
422
|
+
'toast.claude.exists': '設定が既に存在します',
|
|
423
|
+
'toast.claude.keepOne': '最低1つは残してください',
|
|
424
|
+
'toast.claude.externalAuth': '外部認証を使用するため、API Key は不要です',
|
|
425
|
+
'toast.claude.balanceEnabled': 'Claude ローカル負荷分散が有効になりました',
|
|
426
|
+
'toast.claude.balanceDisabled': 'Claude ローカル負荷分散が無効になりました',
|
|
427
|
+
'toast.claude.balanceEnableFail': '負荷分散の有効化に失敗しました',
|
|
428
|
+
'toast.claude.balanceRequireProvider': '最低1つの Claude プロバイダーを追加・設定してください',
|
|
429
|
+
'toast.claude.loadSettingsFail': 'Claude settings の読み込みに失敗しました',
|
|
430
|
+
'validation.claude.nameRequired': '設定名は必須です',
|
|
431
|
+
'validation.claude.nameExists': '名前が既に存在します',
|
|
432
|
+
'validation.claude.apiKeyRequired': 'API Key は必須です',
|
|
433
|
+
'validation.claude.baseUrlRequired': 'Base URL は必須です',
|
|
434
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL は http/https のみサポートします',
|
|
435
|
+
'validation.claude.modelRequired': 'モデル名は必須です',
|
|
436
|
+
'modal.claudeDelete.title': 'Claude 設定の削除',
|
|
437
|
+
'modal.claudeDelete.message': '設定 "{name}" を削除しますか?',
|
|
438
|
+
'modal.claudeDelete.confirm': '削除',
|
|
439
|
+
'modal.claudeDelete.cancel': 'キャンセル',
|
|
394
440
|
|
|
395
441
|
// Basic modals
|
|
396
442
|
'modal.providerAdd.title': 'プロバイダー追加',
|
|
@@ -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
|
|
@@ -233,7 +235,60 @@ const vi = Object.freeze({
|
|
|
233
235
|
'dashboard.doctor.title': 'Doctor',
|
|
234
236
|
'dashboard.doctor.runChecks': 'Chạy kiểm tra',
|
|
235
237
|
'dashboard.doctor.checking': 'Đang kiểm tra...',
|
|
236
|
-
'dashboard.doctor.export': 'Xuất báo cáo'
|
|
238
|
+
'dashboard.doctor.export': 'Xuất báo cáo',
|
|
239
|
+
|
|
240
|
+
// Toasts
|
|
241
|
+
'toast.copy.empty': 'Không có gì để sao chép',
|
|
242
|
+
'toast.copy.ok': 'Đã sao chép',
|
|
243
|
+
'toast.copy.fail': 'Sao chép thất bại',
|
|
244
|
+
'toast.save.ok': 'Đã lưu',
|
|
245
|
+
'toast.save.fail': 'Lưu thất bại',
|
|
246
|
+
'toast.delete.ok': 'Đã xóa',
|
|
247
|
+
'toast.delete.fail': 'Xóa thất bại',
|
|
248
|
+
'toast.operation.success': 'Thao tác thành công',
|
|
249
|
+
'toast.load.fail': 'Tải tệp thất bại',
|
|
250
|
+
'toast.apply.success': 'Đã áp dụng cấu hình',
|
|
251
|
+
'toast.apply.fail': 'Áp dụng cấu hình thất bại',
|
|
252
|
+
'toast.check.success': 'Kiểm tra thành công',
|
|
253
|
+
'toast.check.fail': 'Kiểm tra thất bại',
|
|
254
|
+
'toast.noChanges': 'Không phát hiện thay đổi',
|
|
255
|
+
'toast.template.loadFail': 'Tải mẫu thất bại',
|
|
256
|
+
'toast.template.empty': 'Mẫu không được để trống',
|
|
257
|
+
'toast.template.applied': 'Đã áp dụng mẫu',
|
|
258
|
+
'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',
|
|
259
|
+
'toast.template.applyFail': 'Áp dụng mẫu thất bại',
|
|
260
|
+
'toast.provider.addFail': 'Thêm thất bại',
|
|
261
|
+
'toast.provider.notDeletable': 'Provider này là mục dành riêng, không thể xóa',
|
|
262
|
+
'toast.provider.deletedAndSwitched': 'Đã xóa provider, tự động chuyển sang {provider}{model}',
|
|
263
|
+
'toast.provider.notEditable': 'Provider này là mục dành riêng, không thể chỉnh sửa',
|
|
264
|
+
'toast.provider.updateFail': 'Cập nhật thất bại',
|
|
265
|
+
'toast.provider.resetSuccess': 'Đã cài đặt lại cấu hình{backup}',
|
|
266
|
+
'toast.provider.resetFail': 'Cài đặt lại thất bại',
|
|
267
|
+
'toast.provider.fieldsRequired': 'Tên, URL, API Key và tên mô hình là bắt buộc',
|
|
268
|
+
'toast.provider.urlRequired': 'URL là bắt buộc',
|
|
269
|
+
'toast.claude.modelRequired': 'Vui lòng nhập mô hình',
|
|
270
|
+
'toast.claude.apiKeyRequired': 'Vui lòng cấu hình API Key trước',
|
|
271
|
+
'toast.claude.checkConfig': 'Vui lòng kiểm tra cấu hình Claude',
|
|
272
|
+
'toast.claude.savedWithoutKey': 'Đã lưu (chưa điền API Key)',
|
|
273
|
+
'toast.claude.applied': 'Cấu hình Claude đã được áp dụng',
|
|
274
|
+
'toast.claude.exists': 'Cấu hình đã tồn tại',
|
|
275
|
+
'toast.claude.keepOne': 'Giữ ít nhất một mục',
|
|
276
|
+
'toast.claude.externalAuth': 'Sử dụng xác thực bên ngoài, không cần API Key',
|
|
277
|
+
'toast.claude.balanceEnabled': 'Đã bật cân bằng tải cục bộ Claude',
|
|
278
|
+
'toast.claude.balanceDisabled': 'Đã tắt cân bằng tải cục bộ Claude',
|
|
279
|
+
'toast.claude.balanceEnableFail': 'Không thể bật cân bằng tải',
|
|
280
|
+
'toast.claude.balanceRequireProvider': 'Vui lòng thêm và cấu hình ít nhất một nhà cung cấp Claude',
|
|
281
|
+
'toast.claude.loadSettingsFail': 'Tải cài đặt Claude thất bại',
|
|
282
|
+
'validation.claude.nameRequired': 'Tên cấu hình là bắt buộc',
|
|
283
|
+
'validation.claude.nameExists': 'Tên đã tồn tại',
|
|
284
|
+
'validation.claude.apiKeyRequired': 'API Key là bắt buộc',
|
|
285
|
+
'validation.claude.baseUrlRequired': 'Base URL là bắt buộc',
|
|
286
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL chỉ hỗ trợ http/https',
|
|
287
|
+
'validation.claude.modelRequired': 'Tên mô hình là bắt buộc',
|
|
288
|
+
'modal.claudeDelete.title': 'Xóa cấu hình Claude',
|
|
289
|
+
'modal.claudeDelete.message': 'Xóa cấu hình "{name}"?',
|
|
290
|
+
'modal.claudeDelete.confirm': 'Xóa',
|
|
291
|
+
'modal.claudeDelete.cancel': 'Hủy',
|
|
237
292
|
});
|
|
238
293
|
|
|
239
294
|
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': '打开安装指南',
|
|
@@ -358,7 +360,7 @@ const zh = Object.freeze({
|
|
|
358
360
|
'plugins.builtin.commentPolish.desc': '轻微收敛以下代码注释 {{code}}',
|
|
359
361
|
'plugins.builtin.commentPolish.line1': '轻微收敛以下代码注释',
|
|
360
362
|
'plugins.builtin.ruleAck.name': '规则确认回复',
|
|
361
|
-
'plugins.builtin.ruleAck.desc': '
|
|
363
|
+
'plugins.builtin.ruleAck.desc': '生成规则确认回复',
|
|
362
364
|
'plugins.builtin.ruleAck.line1': '请根据【{{rule}}】,收到请回复',
|
|
363
365
|
|
|
364
366
|
// Toasts
|
|
@@ -386,9 +388,53 @@ const zh = Object.freeze({
|
|
|
386
388
|
'toast.templates.builtinNotDuplicable': '内置模板不可复制',
|
|
387
389
|
'toast.templates.builtinNotDeletable': '内置模板不可删除',
|
|
388
390
|
'toast.templates.deleteTitle': '删除模板',
|
|
389
|
-
'toast.templates.deleteMessage': '
|
|
391
|
+
'toast.templates.deleteMessage': '删除”{name}”?此操作无法撤销。',
|
|
390
392
|
'toast.templates.deleteConfirm': '删除',
|
|
391
393
|
'toast.templates.deleteCancel': '取消',
|
|
394
|
+
'toast.operation.success': '操作成功',
|
|
395
|
+
'toast.load.fail': '加载文件失败',
|
|
396
|
+
'toast.apply.success': '配置已应用',
|
|
397
|
+
'toast.apply.fail': '应用配置失败',
|
|
398
|
+
'toast.check.success': '检查通过',
|
|
399
|
+
'toast.check.fail': '检查失败',
|
|
400
|
+
'toast.noChanges': '未检测到改动',
|
|
401
|
+
'toast.template.loadFail': '加载模板失败',
|
|
402
|
+
'toast.template.empty': '模板不能为空',
|
|
403
|
+
'toast.template.applied': '模板已应用',
|
|
404
|
+
'toast.template.appliedButRefreshFail': '模板已应用,但界面刷新失败,请手动刷新',
|
|
405
|
+
'toast.template.applyFail': '应用模板失败',
|
|
406
|
+
'toast.provider.addFail': '添加失败',
|
|
407
|
+
'toast.provider.notDeletable': '该 provider 为保留项,不可删除',
|
|
408
|
+
'toast.provider.deletedAndSwitched': '已删除提供商,自动切换到 {provider}{model}',
|
|
409
|
+
'toast.provider.notEditable': '该 provider 为保留项,不可编辑',
|
|
410
|
+
'toast.provider.updateFail': '更新失败',
|
|
411
|
+
'toast.provider.resetSuccess': '配置已重装{backup}',
|
|
412
|
+
'toast.provider.resetFail': '重装失败',
|
|
413
|
+
'toast.provider.fieldsRequired': '名称、URL、API Key 和模型名称必填',
|
|
414
|
+
'toast.provider.urlRequired': 'URL 必填',
|
|
415
|
+
'toast.claude.modelRequired': '请输入模型',
|
|
416
|
+
'toast.claude.apiKeyRequired': '请先配置 API Key',
|
|
417
|
+
'toast.claude.checkConfig': '请检查 Claude 配置',
|
|
418
|
+
'toast.claude.savedWithoutKey': '已保存(未填写 API Key)',
|
|
419
|
+
'toast.claude.applied': 'Claude 配置已生效',
|
|
420
|
+
'toast.claude.exists': '配置已存在',
|
|
421
|
+
'toast.claude.keepOne': '至少保留一项',
|
|
422
|
+
'toast.claude.externalAuth': '使用外部认证,无需 API Key',
|
|
423
|
+
'toast.claude.balanceEnabled': 'Claude 本地负载均衡已启用',
|
|
424
|
+
'toast.claude.balanceDisabled': 'Claude 本地负载均衡已关闭',
|
|
425
|
+
'toast.claude.balanceEnableFail': '启用本地负载均衡失败',
|
|
426
|
+
'toast.claude.balanceRequireProvider': '请先添加并配置至少一个 Claude 提供商',
|
|
427
|
+
'toast.claude.loadSettingsFail': '加载 Claude settings 失败',
|
|
428
|
+
'validation.claude.nameRequired': '配置名称不能为空',
|
|
429
|
+
'validation.claude.nameExists': '名称已存在',
|
|
430
|
+
'validation.claude.apiKeyRequired': 'API Key 必填',
|
|
431
|
+
'validation.claude.baseUrlRequired': 'Base URL 必填',
|
|
432
|
+
'validation.claude.baseUrlHttpOnly': 'Base URL 仅支持 http/https',
|
|
433
|
+
'validation.claude.modelRequired': '模型名称必填',
|
|
434
|
+
'modal.claudeDelete.title': '删除 Claude 配置',
|
|
435
|
+
'modal.claudeDelete.message': '确定删除配置 "{name}"?',
|
|
436
|
+
'modal.claudeDelete.confirm': '删除',
|
|
437
|
+
'modal.claudeDelete.cancel': '取消',
|
|
392
438
|
|
|
393
439
|
// Basic modals
|
|
394
440
|
'modal.providerAdd.title': '添加提供商',
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
</div>
|
|
155
155
|
<div class="card-trailing">
|
|
156
156
|
<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('
|
|
157
|
+
<span :class="['pill', config.hasKey ? 'configured' : 'empty']">{{ config.hasKey ? t('common.configured') : t('common.notConfigured') }}</span>
|
|
158
158
|
<div class="card-actions" @click.stop>
|
|
159
159
|
<button class="card-action-btn" @click="openEditConfigModal(name)" :aria-label="t('claude.action.editAria', { name })" :title="t('claude.action.edit')">
|
|
160
160
|
<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>
|
|
@@ -1926,7 +1926,7 @@ return function render(_ctx, _cache) {
|
|
|
1926
1926
|
: _createCommentVNode("v-if", true),
|
|
1927
1927
|
_createElementVNode("span", {
|
|
1928
1928
|
class: _normalizeClass(['pill', config.hasKey ? 'configured' : 'empty'])
|
|
1929
|
-
}, _toDisplayString(config.hasKey ? _ctx.t('
|
|
1929
|
+
}, _toDisplayString(config.hasKey ? _ctx.t('common.configured') : _ctx.t('common.notConfigured')), 3 /* TEXT, CLASS */),
|
|
1930
1930
|
_createElementVNode("div", {
|
|
1931
1931
|
class: "card-actions",
|
|
1932
1932
|
onClick: _withModifiers(() => {}, ["stop"])
|
|
@@ -75,12 +75,18 @@
|
|
|
75
75
|
卡片列表
|
|
76
76
|
============================================ */
|
|
77
77
|
.card-list {
|
|
78
|
-
display:
|
|
79
|
-
|
|
78
|
+
display: grid;
|
|
79
|
+
grid-template-columns: repeat(2, 1fr);
|
|
80
80
|
gap: 10px;
|
|
81
81
|
margin-bottom: 8px;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
@media (max-width: 768px) {
|
|
85
|
+
.card-list {
|
|
86
|
+
grid-template-columns: 1fr;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
84
90
|
/* ============================================
|
|
85
91
|
卡片
|
|
86
92
|
============================================ */
|
|
@@ -368,9 +374,9 @@
|
|
|
368
374
|
状态徽章
|
|
369
375
|
============================================ */
|
|
370
376
|
.pill {
|
|
371
|
-
padding:
|
|
377
|
+
padding: 4px 9px;
|
|
372
378
|
border-radius: var(--radius-full);
|
|
373
|
-
font-size:
|
|
379
|
+
font-size: 9px;
|
|
374
380
|
font-weight: var(--font-weight-caption);
|
|
375
381
|
background-color: rgba(255, 255, 255, 0.8);
|
|
376
382
|
color: var(--color-text-tertiary);
|