codexmate 0.0.22 → 0.0.24
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 +5 -3
- package/README.zh.md +8 -5
- package/cli/auth-profiles.js +23 -7
- package/cli/doctor-core.js +903 -0
- package/cli/import-skills-url.js +334 -0
- package/cli.js +304 -208
- package/lib/cli-models-utils.js +0 -40
- package/lib/cli-network-utils.js +28 -2
- package/package.json +5 -2
- package/plugins/README.md +20 -0
- package/plugins/README.zh-CN.md +20 -0
- package/plugins/prompt-templates/comment-polish/index.mjs +25 -0
- package/plugins/prompt-templates/computed.mjs +253 -0
- package/plugins/prompt-templates/index.mjs +8 -0
- package/plugins/prompt-templates/manifest.mjs +15 -0
- package/plugins/prompt-templates/methods.mjs +619 -0
- package/plugins/prompt-templates/overview.mjs +90 -0
- package/plugins/prompt-templates/ownership.mjs +19 -0
- package/plugins/prompt-templates/rule-ack/index.mjs +21 -0
- package/plugins/prompt-templates/storage.mjs +64 -0
- package/plugins/registry.mjs +16 -0
- package/res/logo-pack.webp +0 -0
- package/web-ui/app.js +68 -34
- package/web-ui/index.html +4 -3
- package/web-ui/modules/app.computed.dashboard.mjs +22 -22
- package/web-ui/modules/app.computed.main-tabs.mjs +9 -2
- package/web-ui/modules/app.methods.agents.mjs +91 -3
- package/web-ui/modules/app.methods.codex-config.mjs +153 -164
- package/web-ui/modules/app.methods.install.mjs +16 -0
- package/web-ui/modules/app.methods.navigation.mjs +76 -0
- package/web-ui/modules/app.methods.runtime.mjs +24 -2
- package/web-ui/modules/app.methods.session-browser.mjs +73 -1
- package/web-ui/modules/app.methods.startup-claude.mjs +12 -0
- package/web-ui/modules/app.methods.task-orchestration.mjs +96 -11
- package/web-ui/modules/config-mode.computed.mjs +1 -3
- package/web-ui/modules/i18n.dict.mjs +2039 -0
- package/web-ui/modules/i18n.mjs +2 -1555
- package/web-ui/modules/plugins.computed.mjs +2 -219
- package/web-ui/modules/plugins.methods.mjs +2 -619
- package/web-ui/modules/plugins.storage.mjs +11 -37
- package/web-ui/modules/sessions-filters-url.mjs +85 -0
- package/web-ui/partials/index/layout-header.html +38 -34
- package/web-ui/partials/index/modal-config-template-agents.html +3 -4
- package/web-ui/partials/index/modal-health-check.html +33 -60
- package/web-ui/partials/index/panel-config-claude.html +56 -15
- package/web-ui/partials/index/panel-config-codex.html +68 -19
- package/web-ui/partials/index/panel-config-openclaw.html +8 -3
- package/web-ui/partials/index/panel-dashboard.html +186 -0
- package/web-ui/partials/index/panel-docs.html +1 -1
- package/web-ui/partials/index/panel-market.html +3 -0
- package/web-ui/partials/index/panel-orchestration.html +105 -111
- package/web-ui/partials/index/panel-plugins.html +48 -12
- package/web-ui/partials/index/panel-sessions.html +12 -3
- package/web-ui/partials/index/panel-settings.html +1 -1
- package/web-ui/partials/index/panel-usage.html +7 -6
- package/web-ui/styles/controls-forms.css +16 -2
- package/web-ui/styles/dashboard.css +274 -0
- package/web-ui/styles/layout-shell.css +11 -5
- package/web-ui/styles/navigation-panels.css +8 -0
- package/web-ui/styles/plugins-panel.css +5 -0
- package/web-ui/styles/sessions-list.css +3 -3
- package/web-ui/styles/sessions-usage.css +37 -0
- package/web-ui/styles/skills-market.css +12 -2
- package/web-ui/styles/task-orchestration.css +57 -11
- package/web-ui/styles.css +1 -0
- package/res/logo.png +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
persistPromptTemplatesToStorage,
|
|
3
|
+
readPromptTemplatesFromStorage,
|
|
4
|
+
readPromptTemplateSelectedIdFromStorage,
|
|
5
|
+
persistPromptTemplateSelectedIdToStorage
|
|
6
|
+
} from './storage.mjs';
|
|
7
|
+
import { buildBuiltinCommentPolishTemplate } from './comment-polish/index.mjs';
|
|
8
|
+
import { buildBuiltinRuleAckTemplate } from './rule-ack/index.mjs';
|
|
9
|
+
|
|
10
|
+
function ensureBuiltinTemplates(rawList, builtins) {
|
|
11
|
+
const list = Array.isArray(rawList) ? rawList.filter(Boolean) : [];
|
|
12
|
+
const builtinList = Array.isArray(builtins) ? builtins.filter(Boolean) : [];
|
|
13
|
+
const rest = list.filter((item) => !(item && item.isBuiltin === true));
|
|
14
|
+
const overridden = new Set(
|
|
15
|
+
rest
|
|
16
|
+
.map((item) => (item && typeof item.id === 'string' ? item.id.trim() : ''))
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
);
|
|
19
|
+
const resolvedBuiltins = builtinList.filter((item) => !(item && overridden.has(item.id)));
|
|
20
|
+
return [...resolvedBuiltins, ...rest];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function loadPromptTemplatesOverview(ctx, options = {}) {
|
|
24
|
+
const app = ctx && typeof ctx === 'object' ? ctx : {};
|
|
25
|
+
const silent = !!(options && options.silent);
|
|
26
|
+
const forceRefresh = !!(options && options.forceRefresh);
|
|
27
|
+
|
|
28
|
+
const shouldReload = forceRefresh || app.promptTemplatesLoadedOnce !== true;
|
|
29
|
+
if (!shouldReload) return true;
|
|
30
|
+
|
|
31
|
+
const t = typeof app.t === 'function' ? app.t : null;
|
|
32
|
+
const rawList = readPromptTemplatesFromStorage(localStorage);
|
|
33
|
+
const normalized = ensureBuiltinTemplates(rawList, [
|
|
34
|
+
buildBuiltinCommentPolishTemplate(t),
|
|
35
|
+
buildBuiltinRuleAckTemplate(t)
|
|
36
|
+
]);
|
|
37
|
+
app.promptTemplatesListRaw = normalized;
|
|
38
|
+
persistPromptTemplatesToStorage(normalized, localStorage);
|
|
39
|
+
|
|
40
|
+
app.promptTemplatesLoadedOnce = true;
|
|
41
|
+
|
|
42
|
+
if (!app.promptTemplatesMode) {
|
|
43
|
+
app.promptTemplatesMode = 'compose';
|
|
44
|
+
}
|
|
45
|
+
if (app.promptTemplatesMode !== 'compose' && app.promptTemplatesMode !== 'manage') {
|
|
46
|
+
app.promptTemplatesMode = 'compose';
|
|
47
|
+
}
|
|
48
|
+
if (app.mainTab === 'plugins') {
|
|
49
|
+
app.promptTemplatesMode = 'compose';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (app.mainTab === 'plugins' && app.promptTemplatesMode === 'compose') {
|
|
53
|
+
const list = Array.isArray(app.promptTemplatesList) ? app.promptTemplatesList : [];
|
|
54
|
+
const storedSelected = readPromptTemplateSelectedIdFromStorage(localStorage);
|
|
55
|
+
const exists = list.some((item) => item && item.id === app.promptComposerSelectedTemplateId);
|
|
56
|
+
const storedExists = storedSelected ? list.some((item) => item && item.id === storedSelected) : false;
|
|
57
|
+
if (storedExists && storedSelected !== app.promptComposerSelectedTemplateId) {
|
|
58
|
+
app.promptComposerSelectedTemplateId = storedSelected;
|
|
59
|
+
} else if (!app.promptComposerSelectedTemplateId || !exists) {
|
|
60
|
+
app.promptComposerSelectedTemplateId = 'builtin_comment_polish';
|
|
61
|
+
}
|
|
62
|
+
persistPromptTemplateSelectedIdToStorage(app.promptComposerSelectedTemplateId, localStorage);
|
|
63
|
+
if (!app.promptComposerVarValuesRaw || typeof app.promptComposerVarValuesRaw !== 'object') {
|
|
64
|
+
app.promptComposerVarValuesRaw = {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (app.promptTemplatesMode === 'manage') {
|
|
69
|
+
const currentSelected = typeof app.promptTemplateSelectedId === 'string'
|
|
70
|
+
? app.promptTemplateSelectedId
|
|
71
|
+
: '';
|
|
72
|
+
const first = Array.isArray(app.promptTemplatesList) && app.promptTemplatesList.length
|
|
73
|
+
? app.promptTemplatesList[0]
|
|
74
|
+
: null;
|
|
75
|
+
if (!currentSelected && first && typeof app.selectPromptTemplate === 'function') {
|
|
76
|
+
app.selectPromptTemplate(first.id);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (app.mainTab === 'plugins' && app.promptTemplatesMode === 'compose' && typeof app.$nextTick === 'function') {
|
|
81
|
+
app.$nextTick(() => {
|
|
82
|
+
const input = app.$refs && app.$refs.promptComposerCodeInput
|
|
83
|
+
? app.$refs.promptComposerCodeInput
|
|
84
|
+
: null;
|
|
85
|
+
if (input && typeof input.focus === 'function') input.focus();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const pluginOwnership = {
|
|
2
|
+
pluginId: 'prompt-templates',
|
|
3
|
+
createdBy: 'ymkiux',
|
|
4
|
+
maintainers: ['ymkiux']
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const templateOwnershipById = {
|
|
8
|
+
builtin_comment_polish: {
|
|
9
|
+
templateId: 'builtin_comment_polish',
|
|
10
|
+
createdBy: 'ymkiux',
|
|
11
|
+
maintainers: ['ymkiux']
|
|
12
|
+
},
|
|
13
|
+
builtin_rule_ack: {
|
|
14
|
+
templateId: 'builtin_rule_ack',
|
|
15
|
+
createdBy: 'ymkiux',
|
|
16
|
+
maintainers: ['ymkiux']
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { pluginOwnership, templateOwnershipById } from '../ownership.mjs';
|
|
2
|
+
|
|
3
|
+
export function buildBuiltinRuleAckTemplate(t) {
|
|
4
|
+
const tr = (key, fallback, params = null) => (typeof t === 'function' ? t(key, params) : fallback);
|
|
5
|
+
const line1 = tr('plugins.builtin.ruleAck.line1', '请根据【{{rule}}】,收到请回复');
|
|
6
|
+
const timestamp = new Date().toISOString();
|
|
7
|
+
const ownership = templateOwnershipById && templateOwnershipById.builtin_rule_ack
|
|
8
|
+
? templateOwnershipById.builtin_rule_ack
|
|
9
|
+
: pluginOwnership;
|
|
10
|
+
return {
|
|
11
|
+
id: 'builtin_rule_ack',
|
|
12
|
+
name: tr('plugins.builtin.ruleAck.name', '规则确认回复'),
|
|
13
|
+
description: tr('plugins.builtin.ruleAck.desc', '请根据【{{rule}}】,收到请回复'),
|
|
14
|
+
template: line1,
|
|
15
|
+
createdAt: timestamp,
|
|
16
|
+
updatedAt: timestamp,
|
|
17
|
+
isBuiltin: true,
|
|
18
|
+
createdBy: ownership && typeof ownership.createdBy === 'string' ? ownership.createdBy : '',
|
|
19
|
+
maintainers: ownership && Array.isArray(ownership.maintainers) ? ownership.maintainers : []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const STORAGE_KEY = 'codexmate.plugins.promptTemplates.v1';
|
|
2
|
+
const SELECTED_TEMPLATE_STORAGE_KEY = 'codexmate.plugins.promptTemplates.selectedTemplateId.v1';
|
|
3
|
+
|
|
4
|
+
export function readPromptTemplatesFromStorage(storage = localStorage) {
|
|
5
|
+
if (!storage) return [];
|
|
6
|
+
let raw = '';
|
|
7
|
+
try {
|
|
8
|
+
raw = storage.getItem(STORAGE_KEY) || '';
|
|
9
|
+
} catch (_) {
|
|
10
|
+
raw = '';
|
|
11
|
+
}
|
|
12
|
+
if (!raw) return [];
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
if (!Array.isArray(parsed)) return [];
|
|
16
|
+
return parsed;
|
|
17
|
+
} catch (_) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function persistPromptTemplatesToStorage(list, storage = localStorage) {
|
|
23
|
+
if (!storage) return false;
|
|
24
|
+
try {
|
|
25
|
+
storage.setItem(STORAGE_KEY, JSON.stringify(Array.isArray(list) ? list : []));
|
|
26
|
+
return true;
|
|
27
|
+
} catch (_) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function clearPromptTemplatesStorage(storage = localStorage) {
|
|
33
|
+
if (!storage) return;
|
|
34
|
+
try {
|
|
35
|
+
storage.removeItem(STORAGE_KEY);
|
|
36
|
+
} catch (_) {}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function readPromptTemplateSelectedIdFromStorage(storage = localStorage) {
|
|
40
|
+
if (!storage) return '';
|
|
41
|
+
let raw = '';
|
|
42
|
+
try {
|
|
43
|
+
raw = storage.getItem(SELECTED_TEMPLATE_STORAGE_KEY) || '';
|
|
44
|
+
} catch (_) {
|
|
45
|
+
raw = '';
|
|
46
|
+
}
|
|
47
|
+
const id = typeof raw === 'string' ? raw.trim() : '';
|
|
48
|
+
return id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function persistPromptTemplateSelectedIdToStorage(templateId, storage = localStorage) {
|
|
52
|
+
if (!storage) return false;
|
|
53
|
+
const id = typeof templateId === 'string' ? templateId.trim() : '';
|
|
54
|
+
try {
|
|
55
|
+
if (!id) {
|
|
56
|
+
storage.removeItem(SELECTED_TEMPLATE_STORAGE_KEY);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
storage.setItem(SELECTED_TEMPLATE_STORAGE_KEY, id);
|
|
60
|
+
return true;
|
|
61
|
+
} catch (_) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { pluginMeta as promptTemplatesMeta } from './prompt-templates/manifest.mjs';
|
|
2
|
+
import { loadPromptTemplatesOverview } from './prompt-templates/overview.mjs';
|
|
3
|
+
|
|
4
|
+
export const pluginsRegistry = [
|
|
5
|
+
{ id: promptTemplatesMeta.id, meta: promptTemplatesMeta, loadOverview: loadPromptTemplatesOverview }
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export function getFirstPluginId() {
|
|
9
|
+
return pluginsRegistry.length ? pluginsRegistry[0].id : '';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getPluginEntry(id) {
|
|
13
|
+
const key = typeof id === 'string' ? id.trim() : '';
|
|
14
|
+
if (!key) return null;
|
|
15
|
+
return pluginsRegistry.find((item) => item && item.id === key) || null;
|
|
16
|
+
}
|
|
Binary file
|
package/web-ui/app.js
CHANGED
|
@@ -30,8 +30,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
30
30
|
data() {
|
|
31
31
|
return {
|
|
32
32
|
lang: 'zh',
|
|
33
|
-
|
|
34
|
-
mainTab: 'docs',
|
|
33
|
+
mainTab: 'dashboard',
|
|
35
34
|
configMode: 'codex',
|
|
36
35
|
currentProvider: '',
|
|
37
36
|
currentModel: '',
|
|
@@ -63,12 +62,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
63
62
|
showEditConfigModal: false,
|
|
64
63
|
showOpenclawConfigModal: false,
|
|
65
64
|
showConfigTemplateModal: false,
|
|
66
|
-
showHealthCheckDialog: false,
|
|
67
65
|
showAgentsModal: false,
|
|
68
66
|
showSkillsModal: false,
|
|
67
|
+
showHealthCheckModal: false,
|
|
69
68
|
// Plugins
|
|
70
69
|
pluginsActiveId: 'prompt-templates',
|
|
71
70
|
pluginsLoading: false,
|
|
71
|
+
pluginsError: '',
|
|
72
72
|
promptTemplatesListRaw: [],
|
|
73
73
|
promptTemplatesLoadedOnce: false,
|
|
74
74
|
promptTemplatesKeyword: '',
|
|
@@ -161,6 +161,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
161
161
|
sessionsUsageTimeRange: '7d',
|
|
162
162
|
sessionsUsageList: [],
|
|
163
163
|
sessionsUsageLoadedOnce: false,
|
|
164
|
+
sessionsUsageLoadedLimit: 0,
|
|
164
165
|
sessionsUsageLoading: false,
|
|
165
166
|
sessionsUsageError: '',
|
|
166
167
|
sessionsList: [],
|
|
@@ -243,38 +244,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
243
244
|
providerSwitchInProgress: false,
|
|
244
245
|
pendingProviderSwitch: '',
|
|
245
246
|
providerSwitchDisplayTarget: '',
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
healthCheckDialogMessages: [],
|
|
250
|
-
healthCheckDialogSending: false,
|
|
251
|
-
healthCheckDialogLastResult: null,
|
|
247
|
+
healthCheckBatchTotal: 0,
|
|
248
|
+
healthCheckBatchDone: 0,
|
|
249
|
+
healthCheckBatchFailed: 0,
|
|
252
250
|
installPackageManager: 'npm',
|
|
253
251
|
installCommandAction: 'install',
|
|
254
252
|
installRegistryPreset: 'default',
|
|
255
253
|
installRegistryCustom: '',
|
|
256
|
-
installStatusTargets:
|
|
257
|
-
{
|
|
258
|
-
id: 'claude',
|
|
259
|
-
name: 'Claude Code CLI',
|
|
260
|
-
packageName: '@anthropic-ai/claude-code',
|
|
261
|
-
installed: false,
|
|
262
|
-
bin: 'claude',
|
|
263
|
-
version: '',
|
|
264
|
-
commandPath: '',
|
|
265
|
-
error: ''
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
id: 'codex',
|
|
269
|
-
name: 'Codex CLI',
|
|
270
|
-
packageName: '@openai/codex',
|
|
271
|
-
installed: false,
|
|
272
|
-
bin: 'codex',
|
|
273
|
-
version: '',
|
|
274
|
-
commandPath: '',
|
|
275
|
-
error: ''
|
|
276
|
-
}
|
|
277
|
-
],
|
|
254
|
+
installStatusTargets: null,
|
|
278
255
|
newProvider: { name: '', url: '', key: '', useTransform: false },
|
|
279
256
|
resetConfigLoading: false,
|
|
280
257
|
editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false },
|
|
@@ -382,7 +359,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
382
359
|
codexImportLoading: false,
|
|
383
360
|
codexAuthProfiles: [],
|
|
384
361
|
forceCompactLayout: false,
|
|
385
|
-
taskOrchestrationTabEnabled:
|
|
362
|
+
taskOrchestrationTabEnabled: true,
|
|
386
363
|
taskOrchestration: {
|
|
387
364
|
loading: false,
|
|
388
365
|
planning: false,
|
|
@@ -396,11 +373,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
396
373
|
followUpsText: '',
|
|
397
374
|
workflowIdsText: '',
|
|
398
375
|
selectedEngine: 'codex',
|
|
399
|
-
|
|
400
|
-
dryRun: false,
|
|
376
|
+
runMode: 'write',
|
|
401
377
|
concurrency: 2,
|
|
402
378
|
autoFixRounds: 1,
|
|
403
379
|
plan: null,
|
|
380
|
+
planFingerprint: '',
|
|
404
381
|
planIssues: [],
|
|
405
382
|
planWarnings: [],
|
|
406
383
|
overviewWarnings: [],
|
|
@@ -430,6 +407,55 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
430
407
|
this.agentsModalTitle = this.t('modal.agents.title');
|
|
431
408
|
this.agentsModalHint = this.t('modal.agents.hint');
|
|
432
409
|
}
|
|
410
|
+
{
|
|
411
|
+
const NAV_STATE_STORAGE_KEY = 'codexmateNavState.v1';
|
|
412
|
+
const mainTabSet = new Set(['dashboard', 'config', 'sessions', 'usage', 'orchestration', 'market', 'plugins', 'docs', 'settings']);
|
|
413
|
+
let restored = null;
|
|
414
|
+
try {
|
|
415
|
+
const raw = localStorage.getItem(NAV_STATE_STORAGE_KEY) || '';
|
|
416
|
+
restored = raw ? JSON.parse(raw) : null;
|
|
417
|
+
} catch (_) {
|
|
418
|
+
restored = null;
|
|
419
|
+
}
|
|
420
|
+
const nextMainTab = restored && typeof restored.mainTab === 'string'
|
|
421
|
+
? restored.mainTab.trim().toLowerCase()
|
|
422
|
+
: '';
|
|
423
|
+
const nextConfigMode = restored && typeof restored.configMode === 'string'
|
|
424
|
+
? restored.configMode.trim().toLowerCase()
|
|
425
|
+
: '';
|
|
426
|
+
let urlMainTab = '';
|
|
427
|
+
try {
|
|
428
|
+
const url = new URL(window.location.href);
|
|
429
|
+
if (url.pathname !== '/session') {
|
|
430
|
+
urlMainTab = String(url.searchParams.get('tab') || '').trim().toLowerCase();
|
|
431
|
+
}
|
|
432
|
+
} catch (_) {
|
|
433
|
+
urlMainTab = '';
|
|
434
|
+
}
|
|
435
|
+
const resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab)
|
|
436
|
+
? urlMainTab
|
|
437
|
+
: nextMainTab;
|
|
438
|
+
if (nextConfigMode && typeof this.switchConfigMode === 'function') {
|
|
439
|
+
this.__navStateRestoring = true;
|
|
440
|
+
try {
|
|
441
|
+
if (nextConfigMode === 'codex' || nextConfigMode === 'claude' || nextConfigMode === 'openclaw') {
|
|
442
|
+
this.configMode = nextConfigMode;
|
|
443
|
+
}
|
|
444
|
+
if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
|
|
445
|
+
this.switchMainTab(resolvedMainTab);
|
|
446
|
+
}
|
|
447
|
+
} finally {
|
|
448
|
+
this.__navStateRestoring = false;
|
|
449
|
+
}
|
|
450
|
+
} else if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
|
|
451
|
+
this.__navStateRestoring = true;
|
|
452
|
+
try {
|
|
453
|
+
this.switchMainTab(resolvedMainTab);
|
|
454
|
+
} finally {
|
|
455
|
+
this.__navStateRestoring = false;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
433
459
|
this.initSessionStandalone();
|
|
434
460
|
this.updateCompactLayoutMode();
|
|
435
461
|
if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
|
|
@@ -506,6 +532,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
506
532
|
if (!startupOk) {
|
|
507
533
|
return;
|
|
508
534
|
}
|
|
535
|
+
if (this.mainTab === 'dashboard') {
|
|
536
|
+
if (!this.__doctorLoadedOnce) {
|
|
537
|
+
this.__doctorLoadedOnce = true;
|
|
538
|
+
if (typeof this.runHealthCheck === 'function') {
|
|
539
|
+
void this.runHealthCheck({ doctor: true, silent: true });
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
509
543
|
void this.refreshClaudeSelectionFromSettings({ silent: true });
|
|
510
544
|
void this.syncDefaultOpenclawConfigEntry({ silent: true });
|
|
511
545
|
};
|
package/web-ui/index.html
CHANGED
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Codex Mate</title>
|
|
7
|
-
<link rel="icon" type="image/
|
|
8
|
-
<link rel="apple-touch-icon" href="/res/logo.
|
|
7
|
+
<link rel="icon" type="image/webp" href="/res/logo-pack.webp">
|
|
8
|
+
<link rel="apple-touch-icon" href="/res/logo-pack.webp">
|
|
9
9
|
<script src="/res/vue.global.prod.js"></script>
|
|
10
10
|
<script src="/res/json5.min.js"></script>
|
|
11
11
|
<link rel="stylesheet" href="/web-ui/styles.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<!-- @include ./partials/index/layout-header.html -->
|
|
15
|
+
<!-- @include ./partials/index/panel-dashboard.html -->
|
|
15
16
|
<!-- @include ./partials/index/panel-config-codex.html -->
|
|
16
17
|
<!-- @include ./partials/index/panel-config-claude.html -->
|
|
17
18
|
<!-- @include ./partials/index/panel-config-openclaw.html -->
|
|
@@ -24,10 +25,10 @@
|
|
|
24
25
|
<!-- @include ./partials/index/panel-plugins.html -->
|
|
25
26
|
<!-- @include ./partials/index/layout-footer.html -->
|
|
26
27
|
<!-- @include ./partials/index/modals-basic.html -->
|
|
27
|
-
<!-- @include ./partials/index/modal-health-check.html -->
|
|
28
28
|
<!-- @include ./partials/index/modal-openclaw-config.html -->
|
|
29
29
|
<!-- @include ./partials/index/modal-config-template-agents.html -->
|
|
30
30
|
<!-- @include ./partials/index/modal-skills.html -->
|
|
31
|
+
<!-- @include ./partials/index/modal-health-check.html -->
|
|
31
32
|
<!-- @include ./partials/index/modal-confirm-toast.html -->
|
|
32
33
|
<script type="module" src="/web-ui/app.js"></script>
|
|
33
34
|
</body>
|
|
@@ -37,7 +37,7 @@ export function createDashboardComputed() {
|
|
|
37
37
|
},
|
|
38
38
|
displayProvidersList() {
|
|
39
39
|
const list = Array.isArray(this.providersList) ? this.providersList : [];
|
|
40
|
-
return list
|
|
40
|
+
return list;
|
|
41
41
|
},
|
|
42
42
|
installTargetCards() {
|
|
43
43
|
const targets = Array.isArray(this.installStatusTargets) ? this.installStatusTargets : [];
|
|
@@ -59,39 +59,39 @@ export function createDashboardComputed() {
|
|
|
59
59
|
},
|
|
60
60
|
inspectorBusyStatus() {
|
|
61
61
|
const tasks = [];
|
|
62
|
-
if (this.loading) tasks.push('
|
|
63
|
-
if (this.sessionsLoading) tasks.push('
|
|
64
|
-
if (this.codexModelsLoading || this.claudeModelsLoading) tasks.push('
|
|
65
|
-
if (this.codexApplying || this.configTemplateApplying || this.openclawApplying) tasks.push('
|
|
66
|
-
if (this.agentsSaving) tasks.push('
|
|
67
|
-
if (this.skillsLoading || this.skillsDeleting || this.skillsScanningImports || this.skillsImporting || this.skillsZipImporting || this.skillsExporting) tasks.push('
|
|
62
|
+
if (this.loading) tasks.push(this.t('dashboard.busy.init'));
|
|
63
|
+
if (this.sessionsLoading) tasks.push(this.t('dashboard.busy.sessions'));
|
|
64
|
+
if (this.codexModelsLoading || this.claudeModelsLoading) tasks.push(this.t('dashboard.busy.models'));
|
|
65
|
+
if (this.codexApplying || this.configTemplateApplying || this.openclawApplying) tasks.push(this.t('dashboard.busy.configApply'));
|
|
66
|
+
if (this.agentsSaving) tasks.push(this.t('dashboard.busy.agents'));
|
|
67
|
+
if (this.skillsLoading || this.skillsDeleting || this.skillsScanningImports || this.skillsImporting || this.skillsZipImporting || this.skillsExporting) tasks.push(this.t('dashboard.busy.skills'));
|
|
68
68
|
if (this.taskOrchestration && (this.taskOrchestration.loading || this.taskOrchestration.planning || this.taskOrchestration.running || this.taskOrchestration.queueAdding || this.taskOrchestration.queueStarting || this.taskOrchestration.retrying || this.taskOrchestration.selectedRunLoading)) {
|
|
69
|
-
tasks.push('
|
|
69
|
+
tasks.push(this.t('dashboard.busy.tasks'));
|
|
70
70
|
}
|
|
71
|
-
return tasks.length ? tasks.join(' / ') : '
|
|
71
|
+
return tasks.length ? tasks.join(' / ') : this.t('dashboard.busy.idle');
|
|
72
72
|
},
|
|
73
73
|
inspectorMessageSummary() {
|
|
74
74
|
const value = typeof this.message === 'string' ? this.message.trim() : '';
|
|
75
|
-
return value || '
|
|
75
|
+
return value || this.t('dashboard.message.none');
|
|
76
76
|
},
|
|
77
77
|
inspectorSessionSourceLabel() {
|
|
78
|
-
if (this.sessionFilterSource === 'codex') return '
|
|
79
|
-
if (this.sessionFilterSource === 'claude') return '
|
|
80
|
-
return '
|
|
78
|
+
if (this.sessionFilterSource === 'codex') return this.t('dashboard.sessionSource.codex');
|
|
79
|
+
if (this.sessionFilterSource === 'claude') return this.t('dashboard.sessionSource.claude');
|
|
80
|
+
return this.t('dashboard.sessionSource.all');
|
|
81
81
|
},
|
|
82
82
|
inspectorSessionPathLabel() {
|
|
83
83
|
const value = typeof this.sessionPathFilter === 'string' ? this.sessionPathFilter.trim() : '';
|
|
84
|
-
return value || '
|
|
84
|
+
return value || this.t('dashboard.sessionPath.all');
|
|
85
85
|
},
|
|
86
86
|
inspectorSessionQueryLabel() {
|
|
87
|
-
if (!this.isSessionQueryEnabled) return '
|
|
87
|
+
if (!this.isSessionQueryEnabled) return this.t('dashboard.sessionQuery.unsupported');
|
|
88
88
|
const value = typeof this.sessionQuery === 'string' ? this.sessionQuery.trim() : '';
|
|
89
|
-
return value || '
|
|
89
|
+
return value || this.t('dashboard.sessionQuery.unset');
|
|
90
90
|
},
|
|
91
91
|
inspectorHealthStatus() {
|
|
92
|
-
if (this.initError) return '
|
|
93
|
-
if (this.loading) return '
|
|
94
|
-
return '
|
|
92
|
+
if (this.initError) return this.t('dashboard.healthStatus.failRead');
|
|
93
|
+
if (this.loading) return this.t('dashboard.healthStatus.initializing');
|
|
94
|
+
return this.t('dashboard.healthStatus.ok');
|
|
95
95
|
},
|
|
96
96
|
inspectorHealthTone() {
|
|
97
97
|
if (this.initError) return 'error';
|
|
@@ -100,12 +100,12 @@ export function createDashboardComputed() {
|
|
|
100
100
|
},
|
|
101
101
|
inspectorModelLoadStatus() {
|
|
102
102
|
if (this.codexModelsLoading || this.claudeModelsLoading) {
|
|
103
|
-
return '
|
|
103
|
+
return this.t('dashboard.modelStatus.loading');
|
|
104
104
|
}
|
|
105
105
|
if (this.modelsSource === 'error' || this.claudeModelsSource === 'error') {
|
|
106
|
-
return '
|
|
106
|
+
return this.t('dashboard.modelStatus.error');
|
|
107
107
|
}
|
|
108
|
-
return '
|
|
108
|
+
return this.t('dashboard.modelStatus.ok');
|
|
109
109
|
},
|
|
110
110
|
installTroubleshootingTips() {
|
|
111
111
|
const platform = this.resolveInstallPlatform();
|
|
@@ -13,12 +13,16 @@ function readTaskOrchestrationDraftMetrics(taskOrchestration) {
|
|
|
13
13
|
const workflowIds = normalizeTaskDraftLines(state.workflowIdsText);
|
|
14
14
|
const followUps = normalizeTaskDraftLines(state.followUpsText);
|
|
15
15
|
const engine = String(state.selectedEngine || 'codex').trim().toLowerCase() === 'workflow' ? 'workflow' : 'codex';
|
|
16
|
+
const runMode = String(state.runMode || 'write').trim().toLowerCase();
|
|
17
|
+
const allowWrite = runMode === 'write';
|
|
18
|
+
const dryRun = runMode === 'dry-run';
|
|
16
19
|
const plan = state.plan && typeof state.plan === 'object' ? state.plan : null;
|
|
17
20
|
const planNodes = Array.isArray(plan && plan.nodes) ? plan.nodes : [];
|
|
18
21
|
const planIssues = Array.isArray(state.planIssues) ? state.planIssues : [];
|
|
19
22
|
const planWarnings = Array.isArray(state.planWarnings) ? state.planWarnings : [];
|
|
20
23
|
return {
|
|
21
24
|
engine,
|
|
25
|
+
runMode,
|
|
22
26
|
title,
|
|
23
27
|
target,
|
|
24
28
|
notes,
|
|
@@ -34,8 +38,8 @@ function readTaskOrchestrationDraftMetrics(taskOrchestration) {
|
|
|
34
38
|
workflowCount: workflowIds.length,
|
|
35
39
|
followUpCount: followUps.length,
|
|
36
40
|
planNodeCount: planNodes.length,
|
|
37
|
-
allowWrite
|
|
38
|
-
dryRun
|
|
41
|
+
allowWrite,
|
|
42
|
+
dryRun
|
|
39
43
|
};
|
|
40
44
|
}
|
|
41
45
|
|
|
@@ -132,6 +136,7 @@ function createTaskDraftReadiness(metrics) {
|
|
|
132
136
|
export function createMainTabsComputed() {
|
|
133
137
|
return {
|
|
134
138
|
mainTabKicker() {
|
|
139
|
+
if (this.mainTab === 'dashboard') return this.t('kicker.dashboard');
|
|
135
140
|
if (this.mainTab === 'config') return this.t('kicker.config');
|
|
136
141
|
if (this.mainTab === 'sessions') return this.t('kicker.sessions');
|
|
137
142
|
if (this.mainTab === 'usage') return this.t('kicker.usage');
|
|
@@ -142,6 +147,7 @@ export function createMainTabsComputed() {
|
|
|
142
147
|
return this.t('kicker.settings');
|
|
143
148
|
},
|
|
144
149
|
mainTabTitle() {
|
|
150
|
+
if (this.mainTab === 'dashboard') return this.t('title.dashboard');
|
|
145
151
|
if (this.mainTab === 'config') return this.t('title.config');
|
|
146
152
|
if (this.mainTab === 'sessions') return this.t('title.sessions');
|
|
147
153
|
if (this.mainTab === 'usage') return this.t('title.usage');
|
|
@@ -152,6 +158,7 @@ export function createMainTabsComputed() {
|
|
|
152
158
|
return this.t('title.settings');
|
|
153
159
|
},
|
|
154
160
|
mainTabSubtitle() {
|
|
161
|
+
if (this.mainTab === 'dashboard') return this.t('subtitle.dashboard');
|
|
155
162
|
if (this.mainTab === 'config') return this.t('subtitle.config');
|
|
156
163
|
if (this.mainTab === 'sessions') return this.t('subtitle.sessions');
|
|
157
164
|
if (this.mainTab === 'usage') return this.t('subtitle.usage');
|