codexmate 0.0.55 → 0.0.57
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.vi.md +2 -0
- package/README.zh.md +2 -0
- package/cli/local-bridge.js +221 -22
- package/cli.js +797 -134
- package/lib/task-orchestrator.js +90 -21
- package/lib/task-workspace-chat.js +292 -0
- package/package.json +2 -2
- package/web-ui/app.js +57 -129
- package/web-ui/modules/app.computed.main-tabs.mjs +304 -7
- package/web-ui/modules/app.computed.session.mjs +210 -0
- package/web-ui/modules/app.methods.agents.mjs +3 -0
- package/web-ui/modules/app.methods.claude-config.mjs +178 -22
- package/web-ui/modules/app.methods.codex-config.mjs +294 -65
- package/web-ui/modules/app.methods.navigation.mjs +71 -84
- package/web-ui/modules/app.methods.openclaw-editing.mjs +3 -6
- package/web-ui/modules/app.methods.providers.mjs +15 -1
- package/web-ui/modules/app.methods.runtime.mjs +7 -2
- package/web-ui/modules/app.methods.session-actions.mjs +25 -12
- package/web-ui/modules/app.methods.session-browser.mjs +23 -54
- package/web-ui/modules/app.methods.session-trash.mjs +0 -1
- package/web-ui/modules/app.methods.startup-claude.mjs +35 -17
- package/web-ui/modules/app.methods.task-orchestration.mjs +347 -8
- package/web-ui/modules/app.methods.tool-config-permissions.mjs +0 -3
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +415 -68
- package/web-ui/modules/config-template-confirm-pref.mjs +2 -3
- package/web-ui/modules/i18n/locales/en.mjs +187 -28
- package/web-ui/modules/i18n/locales/ja.mjs +184 -25
- package/web-ui/modules/i18n/locales/vi.mjs +186 -33
- package/web-ui/modules/i18n/locales/zh-tw.mjs +187 -28
- package/web-ui/modules/i18n/locales/zh.mjs +189 -30
- package/web-ui/modules/i18n.mjs +5 -12
- package/web-ui/modules/provider-default-names.mjs +25 -0
- package/web-ui/modules/sessions-filters-url.mjs +1 -2
- package/web-ui/partials/index/layout-header.html +37 -14
- package/web-ui/partials/index/modal-health-check.html +69 -5
- package/web-ui/partials/index/panel-config-codex.html +2 -2
- package/web-ui/partials/index/panel-orchestration.html +489 -282
- package/web-ui/partials/index/panel-sessions.html +97 -17
- package/web-ui/res/web-ui-render.precompiled.js +1423 -732
- package/web-ui/session-helpers.mjs +4 -1
- package/web-ui/styles/layout-shell.css +157 -1
- package/web-ui/styles/navigation-panels.css +11 -0
- package/web-ui/styles/responsive.css +98 -0
- package/web-ui/styles/sessions-preview.css +212 -2
- package/web-ui/styles/sessions-toolbar-trash.css +61 -18
- package/web-ui/styles/skills-list.css +122 -0
- package/web-ui/styles/task-orchestration.css +2161 -4
- package/web-ui/styles/titles-cards.css +52 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { nextClaudeConfigName } from './provider-default-names.mjs';
|
|
2
|
+
|
|
1
3
|
function normalizeClaudeText(value) {
|
|
2
4
|
return typeof value === 'string' ? value.trim() : '';
|
|
3
5
|
}
|
|
@@ -6,6 +8,19 @@ function normalizeClaudeBaseUrl(value) {
|
|
|
6
8
|
return normalizeClaudeText(value).replace(/\/+$/g, '');
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
function buildDeletedClaudeSettingsFingerprint(config = {}) {
|
|
12
|
+
const safe = config && typeof config === 'object' ? config : {};
|
|
13
|
+
const baseUrl = normalizeClaudeBaseUrl(safe.baseUrl);
|
|
14
|
+
const model = normalizeClaudeText(safe.model);
|
|
15
|
+
if (!baseUrl || !model) return null;
|
|
16
|
+
return {
|
|
17
|
+
baseUrl,
|
|
18
|
+
model,
|
|
19
|
+
providerCacheRef: normalizeClaudeText(safe.providerCacheRef),
|
|
20
|
+
deletedAt: Date.now()
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
9
24
|
function isValidClaudeHttpUrl(value) {
|
|
10
25
|
if (!value) return false;
|
|
11
26
|
try {
|
|
@@ -75,10 +90,41 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
75
90
|
return {
|
|
76
91
|
switchClaudeConfig(name) {
|
|
77
92
|
this.currentClaudeConfig = name;
|
|
78
|
-
|
|
93
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
94
|
+
this.persistWebUiPreferences({ currentClaudeConfig: name || '' });
|
|
95
|
+
}
|
|
79
96
|
this.refreshClaudeModelContext();
|
|
80
97
|
},
|
|
81
98
|
|
|
99
|
+
normalizeStoredClaudeConfigs() {
|
|
100
|
+
const configs = this.claudeConfigs && typeof this.claudeConfigs === 'object' && !Array.isArray(this.claudeConfigs)
|
|
101
|
+
? this.claudeConfigs
|
|
102
|
+
: {};
|
|
103
|
+
let changed = configs !== this.claudeConfigs;
|
|
104
|
+
for (const config of Object.values(configs)) {
|
|
105
|
+
if (!config || typeof config !== 'object') continue;
|
|
106
|
+
if (config.apiKey && config.apiKey.includes('****')) {
|
|
107
|
+
config.apiKey = '';
|
|
108
|
+
config.hasKey = false;
|
|
109
|
+
changed = true;
|
|
110
|
+
}
|
|
111
|
+
const targetApiRaw = typeof config.targetApi === 'string' ? config.targetApi.trim().toLowerCase() : '';
|
|
112
|
+
const previousTargetApi = config.targetApi;
|
|
113
|
+
if (targetApiRaw === 'chat_completions' || targetApiRaw === 'chat-completions' || targetApiRaw === 'chat/completions') {
|
|
114
|
+
config.targetApi = 'chat_completions';
|
|
115
|
+
} else if (targetApiRaw === 'ollama') {
|
|
116
|
+
config.targetApi = 'ollama';
|
|
117
|
+
} else {
|
|
118
|
+
config.targetApi = 'responses';
|
|
119
|
+
}
|
|
120
|
+
if (config.targetApi !== previousTargetApi) {
|
|
121
|
+
changed = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.claudeConfigs = configs;
|
|
125
|
+
return changed;
|
|
126
|
+
},
|
|
127
|
+
|
|
82
128
|
onClaudeModelChange() {
|
|
83
129
|
const name = this.currentClaudeConfig;
|
|
84
130
|
if (!name || name === 'claude-local') {
|
|
@@ -107,13 +153,57 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
107
153
|
},
|
|
108
154
|
|
|
109
155
|
saveClaudeConfigs() {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
156
|
+
if (typeof this.normalizeStoredClaudeConfigs === 'function') {
|
|
157
|
+
this.normalizeStoredClaudeConfigs();
|
|
158
|
+
}
|
|
159
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
160
|
+
this.persistWebUiPreferences({
|
|
161
|
+
claudeConfigs: this.claudeConfigs,
|
|
162
|
+
currentClaudeConfig: this.currentClaudeConfig || ''
|
|
163
|
+
});
|
|
113
164
|
}
|
|
114
165
|
this.syncClaudeBridgeProviders();
|
|
115
166
|
},
|
|
116
167
|
|
|
168
|
+
rememberDeletedClaudeSettingsImport(config) {
|
|
169
|
+
const fingerprint = buildDeletedClaudeSettingsFingerprint(config);
|
|
170
|
+
if (!fingerprint) return;
|
|
171
|
+
const entries = Array.isArray(this.deletedClaudeSettingsImports) ? this.deletedClaudeSettingsImports : [];
|
|
172
|
+
const deduped = entries.filter((entry) => {
|
|
173
|
+
if (!entry || typeof entry !== 'object') return false;
|
|
174
|
+
return normalizeClaudeBaseUrl(entry.baseUrl) !== fingerprint.baseUrl
|
|
175
|
+
|| normalizeClaudeText(entry.model) !== fingerprint.model;
|
|
176
|
+
});
|
|
177
|
+
deduped.push(fingerprint);
|
|
178
|
+
this.deletedClaudeSettingsImports = deduped.slice(-50);
|
|
179
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
180
|
+
this.persistWebUiPreferences({ deletedClaudeSettingsImports: this.deletedClaudeSettingsImports });
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
async applyCurrentClaudeConfigSilently() {
|
|
185
|
+
const name = normalizeClaudeText(this.currentClaudeConfig);
|
|
186
|
+
if (!name || !this.claudeConfigs || !this.claudeConfigs[name]) return false;
|
|
187
|
+
if (typeof this.applyClaudeConfig !== 'function') return false;
|
|
188
|
+
return await this.applyClaudeConfig(name, { silent: true });
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
selectClaudeFallbackConfigName(excludedNames = []) {
|
|
192
|
+
const configs = this.claudeConfigs && typeof this.claudeConfigs === 'object' ? this.claudeConfigs : {};
|
|
193
|
+
const excluded = new Set((Array.isArray(excludedNames) ? excludedNames : [excludedNames])
|
|
194
|
+
.map((name) => normalizeClaudeText(name))
|
|
195
|
+
.filter(Boolean));
|
|
196
|
+
const names = Object.keys(configs).filter((name) => name && !excluded.has(name));
|
|
197
|
+
const applyable = names.find((name) => {
|
|
198
|
+
const config = configs[name] || {};
|
|
199
|
+
return !!(config.apiKey
|
|
200
|
+
|| config.providerCacheRef
|
|
201
|
+
|| config.externalCredentialType
|
|
202
|
+
|| config.targetApi === 'ollama');
|
|
203
|
+
});
|
|
204
|
+
return applyable || names[0] || '';
|
|
205
|
+
},
|
|
206
|
+
|
|
117
207
|
async hydrateClaudeConfigsFromProviderCache(options = {}) {
|
|
118
208
|
const silent = options && options.silent === true;
|
|
119
209
|
try {
|
|
@@ -123,10 +213,10 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
123
213
|
return false;
|
|
124
214
|
}
|
|
125
215
|
const providers = Array.isArray(res.providers) ? res.providers : [];
|
|
126
|
-
if (providers.length === 0) return true;
|
|
127
216
|
const configs = this.claudeConfigs && typeof this.claudeConfigs === 'object' ? this.claudeConfigs : {};
|
|
128
217
|
let changed = false;
|
|
129
218
|
let firstCachedName = '';
|
|
219
|
+
const liveCacheRefs = new Set();
|
|
130
220
|
for (const provider of providers) {
|
|
131
221
|
if (!provider || typeof provider !== 'object') continue;
|
|
132
222
|
const name = normalizeClaudeText(provider.name);
|
|
@@ -134,12 +224,15 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
134
224
|
const model = normalizeClaudeText(provider.model);
|
|
135
225
|
if (!name || !baseUrl || !model) continue;
|
|
136
226
|
if (!firstCachedName) firstCachedName = name;
|
|
227
|
+
const providerCacheRef = normalizeClaudeText(provider.providerCacheRef) || name;
|
|
228
|
+
liveCacheRefs.add(name);
|
|
229
|
+
liveCacheRefs.add(providerCacheRef);
|
|
137
230
|
const cachedConfig = {
|
|
138
231
|
apiKey: '',
|
|
139
232
|
baseUrl,
|
|
140
233
|
model,
|
|
141
234
|
hasKey: provider.hasKey === true,
|
|
142
|
-
providerCacheRef
|
|
235
|
+
providerCacheRef,
|
|
143
236
|
source: 'provider-cache',
|
|
144
237
|
targetApi: normalizeClaudeText(provider.targetApi) || 'responses'
|
|
145
238
|
};
|
|
@@ -152,15 +245,33 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
152
245
|
changed = true;
|
|
153
246
|
}
|
|
154
247
|
}
|
|
248
|
+
for (const [name, existing] of Object.entries(configs)) {
|
|
249
|
+
if (!existing || typeof existing !== 'object') continue;
|
|
250
|
+
const providerCacheRef = normalizeClaudeText(existing.providerCacheRef);
|
|
251
|
+
const source = normalizeClaudeText(existing.source);
|
|
252
|
+
const cacheBacked = source === 'provider-cache' || !!providerCacheRef;
|
|
253
|
+
if (!cacheBacked) continue;
|
|
254
|
+
const ref = providerCacheRef || normalizeClaudeText(name);
|
|
255
|
+
if (liveCacheRefs.has(ref) || liveCacheRefs.has(normalizeClaudeText(name))) continue;
|
|
256
|
+
delete configs[name];
|
|
257
|
+
changed = true;
|
|
258
|
+
}
|
|
155
259
|
this.claudeConfigs = configs;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
260
|
+
const current = normalizeClaudeText(this.currentClaudeConfig);
|
|
261
|
+
if (current && !configs[current]) {
|
|
262
|
+
this.currentClaudeConfig = firstCachedName || Object.keys(configs)[0] || '';
|
|
263
|
+
changed = true;
|
|
264
|
+
} else if (firstCachedName) {
|
|
160
265
|
const currentConfig = current && configs[current] ? configs[current] : null;
|
|
161
|
-
|
|
266
|
+
const currentApplyable = currentConfig && (
|
|
267
|
+
currentConfig.hasKey === true
|
|
268
|
+
|| !!normalizeClaudeText(currentConfig.apiKey)
|
|
269
|
+
|| !!normalizeClaudeText(currentConfig.providerCacheRef)
|
|
270
|
+
|| !!normalizeClaudeText(currentConfig.externalCredentialType)
|
|
271
|
+
|| normalizeClaudeText(currentConfig.targetApi) === 'ollama'
|
|
272
|
+
);
|
|
273
|
+
if (!currentApplyable) {
|
|
162
274
|
this.currentClaudeConfig = firstCachedName;
|
|
163
|
-
try { localStorage.setItem('currentClaudeConfig', firstCachedName); } catch (_) {}
|
|
164
275
|
changed = true;
|
|
165
276
|
}
|
|
166
277
|
}
|
|
@@ -323,6 +434,28 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
323
434
|
await this.applyClaudeConfig(name);
|
|
324
435
|
},
|
|
325
436
|
|
|
437
|
+
async deleteClaudeProviderCacheRef(configOrName) {
|
|
438
|
+
const config = configOrName && typeof configOrName === 'object'
|
|
439
|
+
? configOrName
|
|
440
|
+
: (this.claudeConfigs && this.claudeConfigs[configOrName] ? this.claudeConfigs[configOrName] : null);
|
|
441
|
+
const ref = normalizeClaudeText(config && config.providerCacheRef);
|
|
442
|
+
const source = normalizeClaudeText(config && config.source);
|
|
443
|
+
if (!ref && source !== 'provider-cache') return true;
|
|
444
|
+
const name = ref || normalizeClaudeText(config && config.name) || normalizeClaudeText(configOrName);
|
|
445
|
+
if (!name) return true;
|
|
446
|
+
try {
|
|
447
|
+
const res = await api('delete-provider-cache-record', { name, group: 'claude' });
|
|
448
|
+
if (res && res.error) {
|
|
449
|
+
this.showMessage(res.error, 'error');
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
return true;
|
|
453
|
+
} catch (e) {
|
|
454
|
+
this.showMessage(e && e.message ? e.message : this.t('toast.operation.fail'), 'error');
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
|
|
326
459
|
async deleteClaudeConfig(name) {
|
|
327
460
|
if (Object.keys(this.claudeConfigs).length <= 1) {
|
|
328
461
|
return this.showMessage(this.t('toast.claude.keepOne'), 'error');
|
|
@@ -336,25 +469,43 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
336
469
|
});
|
|
337
470
|
if (!confirmed) return;
|
|
338
471
|
|
|
472
|
+
const config = this.claudeConfigs[name];
|
|
473
|
+
const cacheDeleted = await this.deleteClaudeProviderCacheRef(config || name);
|
|
474
|
+
if (!cacheDeleted) return;
|
|
475
|
+
|
|
476
|
+
if (typeof this.rememberDeletedClaudeSettingsImport === 'function') {
|
|
477
|
+
this.rememberDeletedClaudeSettingsImport(config);
|
|
478
|
+
}
|
|
339
479
|
delete this.claudeConfigs[name];
|
|
340
480
|
if (this.currentClaudeConfig === name) {
|
|
341
|
-
this.currentClaudeConfig =
|
|
481
|
+
this.currentClaudeConfig = this.selectClaudeFallbackConfigName();
|
|
342
482
|
}
|
|
343
483
|
this.saveClaudeConfigs();
|
|
344
484
|
this.showMessage(this.t('toast.operation.success'), 'success');
|
|
345
|
-
this.
|
|
485
|
+
if (this.currentClaudeConfig) {
|
|
486
|
+
await this.applyCurrentClaudeConfigSilently();
|
|
487
|
+
} else {
|
|
488
|
+
this.refreshClaudeModelContext();
|
|
489
|
+
}
|
|
346
490
|
},
|
|
347
491
|
|
|
348
|
-
async applyClaudeConfig(name) {
|
|
492
|
+
async applyClaudeConfig(name, options = {}) {
|
|
493
|
+
const silent = !!(options && options.silent);
|
|
494
|
+
const silentSuccess = silent || !!(options && options.silentSuccess);
|
|
495
|
+
const silentError = silent || !!(options && options.silentError);
|
|
349
496
|
this.currentClaudeConfig = name;
|
|
350
|
-
|
|
497
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
498
|
+
this.persistWebUiPreferences({ currentClaudeConfig: name || '' });
|
|
499
|
+
}
|
|
351
500
|
this.refreshClaudeModelContext();
|
|
352
501
|
const config = this.claudeConfigs[name];
|
|
353
502
|
|
|
354
503
|
if (!config.apiKey && !config.providerCacheRef && config.targetApi !== 'ollama') {
|
|
355
504
|
if (config.externalCredentialType) {
|
|
505
|
+
if (silentError) return false;
|
|
356
506
|
return this.showMessage(this.t('toast.claude.externalAuth'), 'info');
|
|
357
507
|
}
|
|
508
|
+
if (silentError) return false;
|
|
358
509
|
return this.showMessage(this.t('toast.claude.apiKeyRequired'), 'error');
|
|
359
510
|
}
|
|
360
511
|
|
|
@@ -362,15 +513,18 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
362
513
|
try {
|
|
363
514
|
const res = await api('apply-claude-config', { config: { ...config, name } });
|
|
364
515
|
if (res.error || res.success === false) {
|
|
365
|
-
this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
516
|
+
if (!silentError) this.showMessage(res.error || this.t('toast.apply.fail'), 'error');
|
|
517
|
+
return false;
|
|
366
518
|
} else {
|
|
367
|
-
if (this._lastAppliedClaudeKey !== _claudeKey2) {
|
|
519
|
+
if (!silentSuccess && this._lastAppliedClaudeKey !== _claudeKey2) {
|
|
368
520
|
this.showMessage(this.t('toast.apply.success'), 'success');
|
|
369
|
-
this._lastAppliedClaudeKey = _claudeKey2;
|
|
370
521
|
}
|
|
522
|
+
this._lastAppliedClaudeKey = _claudeKey2;
|
|
523
|
+
return true;
|
|
371
524
|
}
|
|
372
525
|
} catch (_) {
|
|
373
|
-
this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
526
|
+
if (!silentError) this.showMessage(this.t('toast.apply.fail'), 'error');
|
|
527
|
+
return false;
|
|
374
528
|
}
|
|
375
529
|
},
|
|
376
530
|
|
|
@@ -378,7 +532,7 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
378
532
|
this.showClaudeConfigModal = false;
|
|
379
533
|
this.showAddClaudeConfigKey = false;
|
|
380
534
|
this.newClaudeConfig = {
|
|
381
|
-
name:
|
|
535
|
+
name: nextClaudeConfigName(this.claudeConfigs),
|
|
382
536
|
apiKey: '',
|
|
383
537
|
externalCredentialType: '',
|
|
384
538
|
baseUrl: '',
|
|
@@ -456,7 +610,9 @@ export function createClaudeConfigMethods(options = {}) {
|
|
|
456
610
|
|
|
457
611
|
async applyClaudeLocalBridge() {
|
|
458
612
|
this.currentClaudeConfig = 'claude-local';
|
|
459
|
-
|
|
613
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
614
|
+
this.persistWebUiPreferences({ currentClaudeConfig: 'claude-local' });
|
|
615
|
+
}
|
|
460
616
|
this.refreshClaudeModelContext();
|
|
461
617
|
|
|
462
618
|
const candidates = this.claudeLocalBridgeCandidateProviders();
|