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
package/web-ui/logic.claude.mjs
CHANGED
|
@@ -69,13 +69,21 @@ export function normalizeClaudeConfig(config) {
|
|
|
69
69
|
const useKey = normalizeClaudeValue(safe.useKey);
|
|
70
70
|
const externalCredentialType = normalizeClaudeValue(safe.externalCredentialType)
|
|
71
71
|
|| (apiKey ? '' : (authToken ? 'auth-token' : (useKey ? 'claude-code-use-key' : '')));
|
|
72
|
+
const targetApiRaw = normalizeClaudeValue(safe.targetApi).toLowerCase();
|
|
73
|
+
let targetApi = 'responses';
|
|
74
|
+
if (targetApiRaw === 'chat_completions' || targetApiRaw === 'chat-completions' || targetApiRaw === 'chat/completions') {
|
|
75
|
+
targetApi = 'chat_completions';
|
|
76
|
+
} else if (targetApiRaw === 'ollama') {
|
|
77
|
+
targetApi = 'ollama';
|
|
78
|
+
}
|
|
72
79
|
return {
|
|
73
80
|
apiKey,
|
|
74
81
|
baseUrl: normalizeClaudeValue(safe.baseUrl),
|
|
75
82
|
model: normalizeClaudeValue(safe.model),
|
|
76
83
|
authToken,
|
|
77
84
|
useKey,
|
|
78
|
-
externalCredentialType
|
|
85
|
+
externalCredentialType,
|
|
86
|
+
targetApi
|
|
79
87
|
};
|
|
80
88
|
}
|
|
81
89
|
|
|
@@ -102,6 +110,60 @@ function normalizeClaudeComparableUrl(value) {
|
|
|
102
110
|
return trimmed.replace(/\/+$/g, '');
|
|
103
111
|
}
|
|
104
112
|
|
|
113
|
+
function isLoopbackClaudeProxyUrl(value) {
|
|
114
|
+
const raw = normalizeClaudeComparableUrl(value);
|
|
115
|
+
if (!raw) return false;
|
|
116
|
+
try {
|
|
117
|
+
const parsed = new URL(raw);
|
|
118
|
+
if (parsed.protocol !== 'http:') return false;
|
|
119
|
+
const host = normalizeClaudeValue(parsed.hostname).toLowerCase();
|
|
120
|
+
return host === '127.0.0.1' || host === 'localhost' || host === '[::1]' || host === '::1';
|
|
121
|
+
} catch (_) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function isLikelyBuiltinClaudeProxySettingsEnv(env = {}) {
|
|
127
|
+
const normalized = normalizeClaudeSettingsEnv(env);
|
|
128
|
+
return !!(
|
|
129
|
+
normalized.baseUrl
|
|
130
|
+
&& normalized.model
|
|
131
|
+
&& /^[a-f0-9]{48}$/i.test(normalized.apiKey)
|
|
132
|
+
&& isLoopbackClaudeProxyUrl(normalized.baseUrl)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function isClaudeTransformConfig(config = {}) {
|
|
137
|
+
const targetApi = normalizeClaudeConfig(config).targetApi;
|
|
138
|
+
return targetApi === 'chat_completions' || targetApi === 'ollama';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function matchBuiltinClaudeProxyConfigFromSettings(claudeConfigs = {}, env = {}, preferredName = '') {
|
|
142
|
+
if (!isLikelyBuiltinClaudeProxySettingsEnv(env)) {
|
|
143
|
+
return '';
|
|
144
|
+
}
|
|
145
|
+
const normalizedSettings = normalizeClaudeSettingsEnv(env);
|
|
146
|
+
const preferred = normalizeClaudeValue(preferredName);
|
|
147
|
+
if (preferred && claudeConfigs && claudeConfigs[preferred]) {
|
|
148
|
+
const config = normalizeClaudeConfig(claudeConfigs[preferred]);
|
|
149
|
+
if (isClaudeTransformConfig(config) && config.model === normalizedSettings.model) {
|
|
150
|
+
return preferred;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const matches = [];
|
|
155
|
+
for (const [name, config] of Object.entries(claudeConfigs || {})) {
|
|
156
|
+
const normalizedConfig = normalizeClaudeConfig(config);
|
|
157
|
+
if (!isClaudeTransformConfig(normalizedConfig)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (normalizedConfig.model === normalizedSettings.model) {
|
|
161
|
+
matches.push(name);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return matches.length === 1 ? matches[0] : '';
|
|
165
|
+
}
|
|
166
|
+
|
|
105
167
|
function hasClaudeCredential(config = {}) {
|
|
106
168
|
return !!(config.apiKey || config.authToken || config.useKey);
|
|
107
169
|
}
|
|
@@ -156,7 +218,8 @@ export function findDuplicateClaudeConfigName(claudeConfigs = {}, config) {
|
|
|
156
218
|
continue;
|
|
157
219
|
}
|
|
158
220
|
if (normalizeClaudeComparableUrl(normalizedExisting.baseUrl) !== comparableUrl
|
|
159
|
-
|| normalizedExisting.model !== normalized.model
|
|
221
|
+
|| normalizedExisting.model !== normalized.model
|
|
222
|
+
|| normalizedExisting.targetApi !== normalized.targetApi) {
|
|
160
223
|
continue;
|
|
161
224
|
}
|
|
162
225
|
if (normalized.apiKey && normalizedExisting.apiKey === normalized.apiKey) {
|
package/web-ui/logic.runtime.mjs
CHANGED
|
@@ -101,10 +101,6 @@ export function shouldForceCompactLayoutMode(options = {}) {
|
|
|
101
101
|
const screenHeight = Number(options.screenHeight || 0);
|
|
102
102
|
const shortEdge = Number(options.shortEdge || (screenWidth > 0 && screenHeight > 0 ? Math.min(screenWidth, screenHeight) : 0));
|
|
103
103
|
const maxTouchPoints = Number(options.maxTouchPoints || 0);
|
|
104
|
-
const userAgent = typeof options.userAgent === 'string' ? options.userAgent : '';
|
|
105
|
-
const isMobileUa = typeof options.isMobileUa === 'boolean'
|
|
106
|
-
? options.isMobileUa
|
|
107
|
-
: /(Android|iPhone|iPad|iPod|Mobile)/i.test(userAgent);
|
|
108
104
|
const coarsePointer = !!options.coarsePointer;
|
|
109
105
|
const noHover = !!options.noHover;
|
|
110
106
|
const isSmallPhysicalScreen = shortEdge > 0 && shortEdge <= 920;
|
|
@@ -115,9 +111,6 @@ export function shouldForceCompactLayoutMode(options = {}) {
|
|
|
115
111
|
if (!isNarrowViewport) {
|
|
116
112
|
return false;
|
|
117
113
|
}
|
|
118
|
-
if (isMobileUa) {
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
114
|
return pointerSuggestsTouchOnly && maxTouchPoints > 0;
|
|
122
115
|
}
|
|
123
116
|
|
|
@@ -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
|
}
|
|
@@ -23,6 +23,10 @@ function getClaudeConfigValidationForContext(vm, mode = 'add') {
|
|
|
23
23
|
const externalCredentialType = normalizeClaudeText(draft && draft.externalCredentialType);
|
|
24
24
|
const baseUrl = normalizeClaudeBaseUrl(draft && draft.baseUrl);
|
|
25
25
|
const model = normalizeClaudeText(draft && draft.model);
|
|
26
|
+
const targetApiRaw = normalizeClaudeText(draft && draft.targetApi).toLowerCase();
|
|
27
|
+
const targetApi = targetApiRaw === 'chat_completions' || targetApiRaw === 'chat-completions' || targetApiRaw === 'chat/completions'
|
|
28
|
+
? 'chat_completions'
|
|
29
|
+
: (targetApiRaw === 'ollama' ? 'ollama' : 'responses');
|
|
26
30
|
const errors = {
|
|
27
31
|
name: '',
|
|
28
32
|
apiKey: '',
|
|
@@ -31,23 +35,23 @@ function getClaudeConfigValidationForContext(vm, mode = 'add') {
|
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
if (!name) {
|
|
34
|
-
errors.name = '
|
|
38
|
+
errors.name = vm.t('validation.claude.nameRequired');
|
|
35
39
|
} else if (mode === 'add' && vm.claudeConfigs && vm.claudeConfigs[name]) {
|
|
36
|
-
errors.name = '
|
|
40
|
+
errors.name = vm.t('validation.claude.nameExists');
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
if (!apiKey && !externalCredentialType) {
|
|
40
|
-
errors.apiKey = '
|
|
43
|
+
if (!apiKey && !externalCredentialType && targetApi !== 'ollama') {
|
|
44
|
+
errors.apiKey = vm.t('validation.claude.apiKeyRequired');
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
if (!baseUrl) {
|
|
44
|
-
errors.baseUrl = '
|
|
48
|
+
errors.baseUrl = vm.t('validation.claude.baseUrlRequired');
|
|
45
49
|
} else if (!isValidClaudeHttpUrl(baseUrl)) {
|
|
46
|
-
errors.baseUrl = '
|
|
50
|
+
errors.baseUrl = vm.t('validation.claude.baseUrlHttpOnly');
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
if (!model) {
|
|
50
|
-
errors.model = '
|
|
54
|
+
errors.model = vm.t('validation.claude.modelRequired');
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
return {
|
|
@@ -57,6 +61,7 @@ function getClaudeConfigValidationForContext(vm, mode = 'add') {
|
|
|
57
61
|
externalCredentialType,
|
|
58
62
|
baseUrl,
|
|
59
63
|
model,
|
|
64
|
+
targetApi,
|
|
60
65
|
errors,
|
|
61
66
|
ok: !errors.name && !errors.apiKey && !errors.baseUrl && !errors.model
|
|
62
67
|
};
|
|
@@ -79,7 +84,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
79
84
|
}
|
|
80
85
|
const model = (this.currentClaudeModel || '').trim();
|
|
81
86
|
if (!model) {
|
|
82
|
-
this.showMessage('
|
|
87
|
+
this.showMessage(this.t('toast.claude.modelRequired'), 'error');
|
|
83
88
|
return;
|
|
84
89
|
}
|
|
85
90
|
const existing = this.claudeConfigs[name] || {};
|
|
@@ -88,8 +93,8 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
88
93
|
this.claudeConfigs[name] = this.mergeClaudeConfig(existing, { model });
|
|
89
94
|
this.saveClaudeConfigs();
|
|
90
95
|
this.updateClaudeModelsCurrent();
|
|
91
|
-
if (!this.claudeConfigs[name].apiKey && !this.claudeConfigs[name].externalCredentialType) {
|
|
92
|
-
this.showMessage('
|
|
96
|
+
if (!this.claudeConfigs[name].apiKey && !this.claudeConfigs[name].externalCredentialType && this.claudeConfigs[name].targetApi !== 'ollama') {
|
|
97
|
+
this.showMessage(this.t('toast.claude.apiKeyRequired'), 'error');
|
|
93
98
|
return;
|
|
94
99
|
}
|
|
95
100
|
this.applyClaudeConfig(name);
|
|
@@ -115,8 +120,10 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
115
120
|
this.newClaudeConfig = {
|
|
116
121
|
name: '',
|
|
117
122
|
apiKey: config.apiKey || '',
|
|
123
|
+
externalCredentialType: config.externalCredentialType || '',
|
|
118
124
|
baseUrl: config.baseUrl || '',
|
|
119
|
-
model: config.model || ''
|
|
125
|
+
model: config.model || '',
|
|
126
|
+
targetApi: config.targetApi || 'responses'
|
|
120
127
|
};
|
|
121
128
|
this.showAddClaudeConfigKey = false;
|
|
122
129
|
this.showClaudeConfigModal = true;
|
|
@@ -144,7 +151,8 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
144
151
|
apiKey: config.apiKey || '',
|
|
145
152
|
externalCredentialType: config.externalCredentialType || '',
|
|
146
153
|
baseUrl: config.baseUrl || '',
|
|
147
|
-
model: config.model || ''
|
|
154
|
+
model: config.model || '',
|
|
155
|
+
targetApi: config.targetApi || 'responses'
|
|
148
156
|
};
|
|
149
157
|
this.showEditClaudeConfigKey = false;
|
|
150
158
|
this.showEditConfigModal = true;
|
|
@@ -153,15 +161,17 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
153
161
|
updateConfig() {
|
|
154
162
|
const validation = getClaudeConfigValidationForContext(this, 'edit');
|
|
155
163
|
if (!validation.ok) {
|
|
156
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
164
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
157
165
|
}
|
|
158
166
|
const name = validation.name;
|
|
159
167
|
this.editingConfig.apiKey = validation.apiKey;
|
|
168
|
+
this.editingConfig.externalCredentialType = validation.externalCredentialType;
|
|
160
169
|
this.editingConfig.baseUrl = validation.baseUrl;
|
|
161
170
|
this.editingConfig.model = validation.model;
|
|
171
|
+
this.editingConfig.targetApi = validation.targetApi;
|
|
162
172
|
this.claudeConfigs[name] = this.mergeClaudeConfig(this.claudeConfigs[name], this.editingConfig);
|
|
163
173
|
this.saveClaudeConfigs();
|
|
164
|
-
this.showMessage('
|
|
174
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
165
175
|
this.closeEditConfigModal();
|
|
166
176
|
if (name === this.currentClaudeConfig) {
|
|
167
177
|
this.refreshClaudeModelContext();
|
|
@@ -171,7 +181,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
171
181
|
closeEditConfigModal() {
|
|
172
182
|
this.showEditConfigModal = false;
|
|
173
183
|
this.showEditClaudeConfigKey = false;
|
|
174
|
-
this.editingConfig = { name: '', apiKey: '', externalCredentialType: '', baseUrl: '', model: '' };
|
|
184
|
+
this.editingConfig = { name: '', apiKey: '', externalCredentialType: '', baseUrl: '', model: '', targetApi: 'responses' };
|
|
175
185
|
},
|
|
176
186
|
|
|
177
187
|
toggleEditClaudeConfigKey() {
|
|
@@ -181,18 +191,20 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
181
191
|
async saveAndApplyConfig() {
|
|
182
192
|
const validation = getClaudeConfigValidationForContext(this, 'edit');
|
|
183
193
|
if (!validation.ok) {
|
|
184
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
194
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
185
195
|
}
|
|
186
196
|
const name = validation.name;
|
|
187
197
|
this.editingConfig.apiKey = validation.apiKey;
|
|
198
|
+
this.editingConfig.externalCredentialType = validation.externalCredentialType;
|
|
188
199
|
this.editingConfig.baseUrl = validation.baseUrl;
|
|
189
200
|
this.editingConfig.model = validation.model;
|
|
201
|
+
this.editingConfig.targetApi = validation.targetApi;
|
|
190
202
|
this.claudeConfigs[name] = this.mergeClaudeConfig(this.claudeConfigs[name], this.editingConfig);
|
|
191
203
|
this.saveClaudeConfigs();
|
|
192
204
|
|
|
193
205
|
const config = this.claudeConfigs[name];
|
|
194
|
-
if (!config.apiKey) {
|
|
195
|
-
this.showMessage('
|
|
206
|
+
if (!config.apiKey && config.targetApi !== 'ollama') {
|
|
207
|
+
this.showMessage(this.t('toast.claude.savedWithoutKey'), 'info');
|
|
196
208
|
this.closeEditConfigModal();
|
|
197
209
|
if (name === this.currentClaudeConfig) {
|
|
198
210
|
this.refreshClaudeModelContext();
|
|
@@ -200,58 +212,60 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
200
212
|
return;
|
|
201
213
|
}
|
|
202
214
|
|
|
203
|
-
const _claudeKey = `${name}|${config.apiKey || ""}|${config.baseUrl || ""}|${config.model || ""}`;
|
|
215
|
+
const _claudeKey = `${name}|${config.apiKey || ""}|${config.baseUrl || ""}|${config.model || ""}|${config.targetApi || "responses"}`;
|
|
204
216
|
try {
|
|
205
|
-
const res = await api('apply-claude-config', { config });
|
|
217
|
+
const res = await api('apply-claude-config', { config: { ...config, name } });
|
|
206
218
|
if (res.error || res.success === false) {
|
|
207
|
-
this.showMessage(res.error || '
|
|
219
|
+
this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
208
220
|
} else {
|
|
209
221
|
this.currentClaudeConfig = name;
|
|
210
222
|
if (this._lastAppliedClaudeKey !== _claudeKey) {
|
|
211
|
-
this.showMessage('
|
|
223
|
+
this.showMessage(this.t('toast.claude.applied'), 'success');
|
|
212
224
|
this._lastAppliedClaudeKey = _claudeKey;
|
|
213
225
|
}
|
|
214
226
|
this.closeEditConfigModal();
|
|
215
227
|
this.refreshClaudeModelContext();
|
|
216
228
|
}
|
|
217
229
|
} catch (_) {
|
|
218
|
-
this.showMessage('
|
|
230
|
+
this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
219
231
|
}
|
|
220
232
|
},
|
|
221
233
|
|
|
222
234
|
addClaudeConfig() {
|
|
223
235
|
const validation = getClaudeConfigValidationForContext(this, 'add');
|
|
224
236
|
if (!validation.ok) {
|
|
225
|
-
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || '
|
|
237
|
+
return this.showMessage(validation.errors.name || validation.errors.apiKey || validation.errors.baseUrl || validation.errors.model || this.t('toast.claude.checkConfig'), 'error');
|
|
226
238
|
}
|
|
227
239
|
this.newClaudeConfig.name = validation.name;
|
|
228
240
|
this.newClaudeConfig.apiKey = validation.apiKey;
|
|
241
|
+
this.newClaudeConfig.externalCredentialType = validation.externalCredentialType;
|
|
229
242
|
this.newClaudeConfig.baseUrl = validation.baseUrl;
|
|
230
243
|
this.newClaudeConfig.model = validation.model;
|
|
244
|
+
this.newClaudeConfig.targetApi = validation.targetApi;
|
|
231
245
|
const name = validation.name;
|
|
232
246
|
const duplicateName = this.findDuplicateClaudeConfigName(this.newClaudeConfig);
|
|
233
247
|
if (duplicateName) {
|
|
234
|
-
return this.showMessage('
|
|
248
|
+
return this.showMessage(this.t('toast.claude.exists'), 'info');
|
|
235
249
|
}
|
|
236
250
|
|
|
237
251
|
this.claudeConfigs[name] = this.mergeClaudeConfig({}, this.newClaudeConfig);
|
|
238
252
|
|
|
239
253
|
this.currentClaudeConfig = name;
|
|
240
254
|
this.saveClaudeConfigs();
|
|
241
|
-
this.showMessage('
|
|
255
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
242
256
|
this.closeClaudeConfigModal();
|
|
243
257
|
this.refreshClaudeModelContext();
|
|
244
258
|
},
|
|
245
259
|
|
|
246
260
|
async deleteClaudeConfig(name) {
|
|
247
261
|
if (Object.keys(this.claudeConfigs).length <= 1) {
|
|
248
|
-
return this.showMessage('
|
|
262
|
+
return this.showMessage(this.t('toast.claude.keepOne'), 'error');
|
|
249
263
|
}
|
|
250
264
|
const confirmed = await this.requestConfirmDialog({
|
|
251
|
-
title: '
|
|
252
|
-
message:
|
|
253
|
-
confirmText: '
|
|
254
|
-
cancelText: '
|
|
265
|
+
title: this.t('modal.claudeDelete.title'),
|
|
266
|
+
message: this.t('modal.claudeDelete.message', { name }),
|
|
267
|
+
confirmText: this.t('modal.claudeDelete.confirm'),
|
|
268
|
+
cancelText: this.t('modal.claudeDelete.cancel'),
|
|
255
269
|
danger: true
|
|
256
270
|
});
|
|
257
271
|
if (!confirmed) return;
|
|
@@ -261,7 +275,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
261
275
|
this.currentClaudeConfig = Object.keys(this.claudeConfigs)[0];
|
|
262
276
|
}
|
|
263
277
|
this.saveClaudeConfigs();
|
|
264
|
-
this.showMessage('
|
|
278
|
+
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
265
279
|
this.refreshClaudeModelContext();
|
|
266
280
|
},
|
|
267
281
|
|
|
@@ -271,26 +285,26 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
271
285
|
this.refreshClaudeModelContext();
|
|
272
286
|
const config = this.claudeConfigs[name];
|
|
273
287
|
|
|
274
|
-
if (!config.apiKey) {
|
|
288
|
+
if (!config.apiKey && config.targetApi !== 'ollama') {
|
|
275
289
|
if (config.externalCredentialType) {
|
|
276
|
-
return this.showMessage('
|
|
290
|
+
return this.showMessage(this.t('toast.claude.externalAuth'), 'info');
|
|
277
291
|
}
|
|
278
|
-
return this.showMessage('
|
|
292
|
+
return this.showMessage(this.t('toast.claude.apiKeyRequired'), 'error');
|
|
279
293
|
}
|
|
280
294
|
|
|
281
|
-
const _claudeKey2 = `${name}|${config.apiKey || ""}|${config.baseUrl || ""}|${config.model || ""}`;
|
|
295
|
+
const _claudeKey2 = `${name}|${config.apiKey || ""}|${config.baseUrl || ""}|${config.model || ""}|${config.targetApi || "responses"}`;
|
|
282
296
|
try {
|
|
283
|
-
const res = await api('apply-claude-config', { config });
|
|
297
|
+
const res = await api('apply-claude-config', { config: { ...config, name } });
|
|
284
298
|
if (res.error || res.success === false) {
|
|
285
|
-
this.showMessage(res.error || '
|
|
299
|
+
this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
286
300
|
} else {
|
|
287
301
|
if (this._lastAppliedClaudeKey !== _claudeKey2) {
|
|
288
|
-
this.showMessage('
|
|
302
|
+
this.showMessage(this.t('toast.apply.success'), 'success');
|
|
289
303
|
this._lastAppliedClaudeKey = _claudeKey2;
|
|
290
304
|
}
|
|
291
305
|
}
|
|
292
306
|
} catch (_) {
|
|
293
|
-
this.showMessage('
|
|
307
|
+
this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
294
308
|
}
|
|
295
309
|
},
|
|
296
310
|
|
|
@@ -300,8 +314,10 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
300
314
|
this.newClaudeConfig = {
|
|
301
315
|
name: '',
|
|
302
316
|
apiKey: '',
|
|
317
|
+
externalCredentialType: '',
|
|
303
318
|
baseUrl: '',
|
|
304
|
-
model: ''
|
|
319
|
+
model: '',
|
|
320
|
+
targetApi: 'responses'
|
|
305
321
|
};
|
|
306
322
|
},
|
|
307
323
|
|
|
@@ -328,12 +344,12 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
328
344
|
return;
|
|
329
345
|
}
|
|
330
346
|
if (enable) {
|
|
331
|
-
this.showMessage('
|
|
347
|
+
this.showMessage(this.t('toast.claude.balanceEnabled'), 'success');
|
|
332
348
|
} else {
|
|
333
|
-
this.showMessage('
|
|
349
|
+
this.showMessage(this.t('toast.claude.balanceDisabled'), 'success');
|
|
334
350
|
}
|
|
335
351
|
} catch (e) {
|
|
336
|
-
this.showMessage('
|
|
352
|
+
this.showMessage(this.t('toast.operation.fail'), 'error');
|
|
337
353
|
}
|
|
338
354
|
},
|
|
339
355
|
|
|
@@ -379,18 +395,18 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
379
395
|
|
|
380
396
|
const candidates = this.claudeLocalBridgeCandidateProviders();
|
|
381
397
|
if (candidates.length === 0) {
|
|
382
|
-
return this.showMessage('
|
|
398
|
+
return this.showMessage(this.t('toast.claude.balanceRequireProvider'), 'error');
|
|
383
399
|
}
|
|
384
400
|
|
|
385
401
|
try {
|
|
386
402
|
const res = await api('claude-local-bridge-toggle', { enable: true });
|
|
387
403
|
if (res.error) {
|
|
388
|
-
this.showMessage(res.error || '
|
|
404
|
+
this.showMessage(res.error || this.t('toast.claude.balanceEnableFail'), 'error');
|
|
389
405
|
return;
|
|
390
406
|
}
|
|
391
|
-
this.showMessage('
|
|
407
|
+
this.showMessage(this.t('toast.claude.balanceEnabled'), 'success');
|
|
392
408
|
} catch (e) {
|
|
393
|
-
this.showMessage('
|
|
409
|
+
this.showMessage(this.t('toast.claude.balanceEnableFail'), 'error');
|
|
394
410
|
}
|
|
395
411
|
},
|
|
396
412
|
|
|
@@ -405,7 +421,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
405
421
|
this.configTemplateContext = 'claude';
|
|
406
422
|
this.showConfigTemplateModal = true;
|
|
407
423
|
} catch (e) {
|
|
408
|
-
this.showMessage('
|
|
424
|
+
this.showMessage(this.t('toast.claude.loadSettingsFail'), 'error');
|
|
409
425
|
}
|
|
410
426
|
}
|
|
411
427
|
};
|
|
@@ -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
|
}
|
|
@@ -89,7 +89,7 @@ export function createAppMethods() {
|
|
|
89
89
|
api,
|
|
90
90
|
defaultOpenclawTemplate: DEFAULT_OPENCLAW_TEMPLATE
|
|
91
91
|
}),
|
|
92
|
-
...createInstallMethods(),
|
|
92
|
+
...createInstallMethods({ api }),
|
|
93
93
|
...createRuntimeMethods({ api }),
|
|
94
94
|
...createTaskOrchestrationMethods({ api })
|
|
95
95
|
};
|