codexmate 0.0.24 → 0.0.26

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.
Files changed (136) hide show
  1. package/README.md +416 -391
  2. package/README.zh.md +349 -324
  3. package/cli/agents-files.js +224 -224
  4. package/cli/archive-helpers.js +446 -446
  5. package/cli/auth-profiles.js +375 -375
  6. package/cli/builtin-proxy.js +1079 -1044
  7. package/cli/claude-proxy.js +1022 -998
  8. package/cli/config-bootstrap.js +384 -384
  9. package/cli/config-health.js +338 -338
  10. package/cli/doctor-core.js +903 -903
  11. package/cli/import-skills-url.js +356 -334
  12. package/cli/openai-bridge.js +997 -950
  13. package/cli/openclaw-config.js +629 -629
  14. package/cli/session-convert-args.js +65 -0
  15. package/cli/session-convert-io.js +82 -0
  16. package/cli/session-convert.js +43 -0
  17. package/cli/session-usage.concurrent.js +28 -28
  18. package/cli/session-usage.js +118 -112
  19. package/cli/session-usage.models.js +176 -176
  20. package/cli/skills.js +1141 -1141
  21. package/cli/zip-commands.js +510 -510
  22. package/cli.js +15218 -13310
  23. package/lib/automation.js +404 -0
  24. package/lib/cli-file-utils.js +151 -151
  25. package/lib/cli-models-utils.js +379 -379
  26. package/lib/cli-network-utils.js +190 -190
  27. package/lib/cli-path-utils.js +85 -69
  28. package/lib/cli-session-utils.js +121 -121
  29. package/lib/cli-sessions.js +417 -386
  30. package/lib/cli-utils.js +155 -155
  31. package/lib/download-artifacts.js +92 -77
  32. package/lib/mcp-stdio.js +453 -440
  33. package/lib/task-orchestrator.js +869 -869
  34. package/lib/text-diff.js +303 -303
  35. package/lib/workflow-engine.js +340 -340
  36. package/package.json +74 -77
  37. package/plugins/README.md +20 -20
  38. package/plugins/README.zh-CN.md +20 -20
  39. package/plugins/prompt-templates/comment-polish/index.mjs +25 -25
  40. package/plugins/prompt-templates/computed.mjs +253 -253
  41. package/plugins/prompt-templates/index.mjs +8 -8
  42. package/plugins/prompt-templates/manifest.mjs +15 -15
  43. package/plugins/prompt-templates/methods.mjs +619 -619
  44. package/plugins/prompt-templates/overview.mjs +90 -90
  45. package/plugins/prompt-templates/ownership.mjs +19 -19
  46. package/plugins/prompt-templates/rule-ack/index.mjs +21 -21
  47. package/plugins/prompt-templates/storage.mjs +64 -64
  48. package/plugins/registry.mjs +16 -16
  49. package/web-ui/app.js +625 -609
  50. package/web-ui/index.html +35 -35
  51. package/web-ui/logic.agents-diff.mjs +386 -386
  52. package/web-ui/logic.claude.mjs +168 -168
  53. package/web-ui/logic.mjs +5 -5
  54. package/web-ui/logic.runtime.mjs +128 -128
  55. package/web-ui/logic.session-convert.mjs +70 -0
  56. package/web-ui/logic.sessions.mjs +709 -614
  57. package/web-ui/modules/api.mjs +90 -90
  58. package/web-ui/modules/app.computed.dashboard.mjs +171 -126
  59. package/web-ui/modules/app.computed.index.mjs +17 -17
  60. package/web-ui/modules/app.computed.main-tabs.mjs +205 -205
  61. package/web-ui/modules/app.computed.session.mjs +946 -653
  62. package/web-ui/modules/app.constants.mjs +15 -15
  63. package/web-ui/modules/app.methods.agents.mjs +632 -632
  64. package/web-ui/modules/app.methods.claude-config.mjs +179 -174
  65. package/web-ui/modules/app.methods.codex-config.mjs +860 -784
  66. package/web-ui/modules/app.methods.index.mjs +92 -92
  67. package/web-ui/modules/app.methods.install.mjs +205 -177
  68. package/web-ui/modules/app.methods.navigation.mjs +743 -695
  69. package/web-ui/modules/app.methods.openclaw-core.mjs +814 -814
  70. package/web-ui/modules/app.methods.openclaw-editing.mjs +372 -372
  71. package/web-ui/modules/app.methods.openclaw-persist.mjs +369 -369
  72. package/web-ui/modules/app.methods.providers.mjs +404 -404
  73. package/web-ui/modules/app.methods.runtime.mjs +345 -345
  74. package/web-ui/modules/app.methods.session-actions.mjs +596 -537
  75. package/web-ui/modules/app.methods.session-browser.mjs +985 -698
  76. package/web-ui/modules/app.methods.session-timeline.mjs +479 -448
  77. package/web-ui/modules/app.methods.session-trash.mjs +424 -422
  78. package/web-ui/modules/app.methods.startup-claude.mjs +522 -417
  79. package/web-ui/modules/app.methods.task-orchestration.mjs +556 -556
  80. package/web-ui/modules/config-mode.computed.mjs +124 -124
  81. package/web-ui/modules/config-template-confirm-pref.mjs +33 -33
  82. package/web-ui/modules/i18n.dict.mjs +2113 -2039
  83. package/web-ui/modules/i18n.mjs +56 -56
  84. package/web-ui/modules/plugins.computed.mjs +3 -3
  85. package/web-ui/modules/plugins.methods.mjs +3 -3
  86. package/web-ui/modules/plugins.storage.mjs +11 -11
  87. package/web-ui/modules/sessions-filters-url.mjs +85 -85
  88. package/web-ui/modules/skills.computed.mjs +107 -107
  89. package/web-ui/modules/skills.methods.mjs +481 -481
  90. package/web-ui/partials/index/layout-footer.html +13 -13
  91. package/web-ui/partials/index/layout-header.html +475 -465
  92. package/web-ui/partials/index/modal-config-template-agents.html +174 -174
  93. package/web-ui/partials/index/modal-confirm-toast.html +32 -32
  94. package/web-ui/partials/index/modal-health-check.html +45 -45
  95. package/web-ui/partials/index/modal-openclaw-config.html +280 -280
  96. package/web-ui/partials/index/modal-skills.html +200 -200
  97. package/web-ui/partials/index/modals-basic.html +165 -165
  98. package/web-ui/partials/index/panel-config-claude.html +184 -179
  99. package/web-ui/partials/index/panel-config-codex.html +283 -283
  100. package/web-ui/partials/index/panel-config-openclaw.html +83 -83
  101. package/web-ui/partials/index/panel-dashboard.html +186 -186
  102. package/web-ui/partials/index/panel-docs.html +147 -147
  103. package/web-ui/partials/index/panel-market.html +177 -177
  104. package/web-ui/partials/index/panel-orchestration.html +391 -391
  105. package/web-ui/partials/index/panel-plugins.html +279 -279
  106. package/web-ui/partials/index/panel-sessions.html +326 -301
  107. package/web-ui/partials/index/panel-settings.html +258 -258
  108. package/web-ui/partials/index/panel-usage.html +342 -354
  109. package/{res → web-ui/res}/json5.min.js +1 -1
  110. package/{res → web-ui/res}/vue.global.prod.js +13 -13
  111. package/web-ui/session-helpers.mjs +576 -573
  112. package/web-ui/source-bundle.cjs +233 -233
  113. package/web-ui/styles/base-theme.css +268 -264
  114. package/web-ui/styles/controls-forms.css +423 -376
  115. package/web-ui/styles/dashboard.css +274 -274
  116. package/web-ui/styles/docs-panel.css +247 -247
  117. package/web-ui/styles/feedback.css +108 -108
  118. package/web-ui/styles/health-check-dialog.css +144 -144
  119. package/web-ui/styles/layout-shell.css +603 -602
  120. package/web-ui/styles/modals-core.css +464 -464
  121. package/web-ui/styles/navigation-panels.css +390 -390
  122. package/web-ui/styles/openclaw-structured.css +266 -266
  123. package/web-ui/styles/plugins-panel.css +523 -523
  124. package/web-ui/styles/responsive.css +454 -456
  125. package/web-ui/styles/sessions-list.css +415 -400
  126. package/web-ui/styles/sessions-preview.css +411 -411
  127. package/web-ui/styles/sessions-toolbar-trash.css +330 -268
  128. package/web-ui/styles/sessions-usage.css +945 -888
  129. package/web-ui/styles/settings-panel.css +166 -166
  130. package/web-ui/styles/skills-list.css +303 -303
  131. package/web-ui/styles/skills-market.css +406 -406
  132. package/web-ui/styles/task-orchestration.css +822 -822
  133. package/web-ui/styles/titles-cards.css +408 -408
  134. package/web-ui/styles.css +21 -21
  135. package/web-ui.html +17 -17
  136. /package/{res → web-ui/res}/logo-pack.webp +0 -0
package/web-ui/app.js CHANGED
@@ -1,609 +1,625 @@
1
- import {
2
- DEFAULT_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
3
- DEFAULT_MODEL_CONTEXT_WINDOW,
4
- DEFAULT_OPENCLAW_TEMPLATE,
5
- SESSION_TRASH_PAGE_SIZE
6
- } from './modules/app.constants.mjs';
7
- import { createAppComputed } from './modules/app.computed.index.mjs';
8
- import { createAppMethods } from './modules/app.methods.index.mjs';
9
- import { loadConfigTemplateDiffConfirmEnabledFromStorage } from './modules/config-template-confirm-pref.mjs';
10
-
11
- document.addEventListener('DOMContentLoaded', () => {
12
- if (typeof Vue === 'undefined') {
13
- console.error('Vue 库未能在 DOMContentLoaded 触发前加载完成。');
14
- const fallbackTarget = document.querySelector('#app') || document.querySelector('[v-cloak]');
15
- if (fallbackTarget) {
16
- fallbackTarget.removeAttribute('v-cloak');
17
- fallbackTarget.classList.remove('v-cloak');
18
- fallbackTarget.innerHTML = '';
19
- const notice = document.createElement('div');
20
- notice.className = 'fallback-message';
21
- notice.textContent = 'Web UI 加载失败:Vue 未加载。请检查网络或刷新页面。';
22
- fallbackTarget.appendChild(notice);
23
- }
24
- return;
25
- }
26
-
27
- const { createApp } = Vue;
28
-
29
- const app = createApp({
30
- data() {
31
- return {
32
- lang: 'zh',
33
- mainTab: 'dashboard',
34
- configMode: 'codex',
35
- currentProvider: '',
36
- currentModel: '',
37
- serviceTier: 'fast',
38
- modelReasoningEffort: 'medium',
39
- modelContextWindowInput: String(DEFAULT_MODEL_CONTEXT_WINDOW),
40
- modelAutoCompactTokenLimitInput: String(DEFAULT_MODEL_AUTO_COMPACT_TOKEN_LIMIT),
41
- editingCodexBudgetField: '',
42
- providersList: [],
43
- models: [],
44
- codexModelsLoading: false,
45
- modelsSource: 'remote',
46
- modelsHasCurrent: true,
47
- claudeModels: [],
48
- claudeModelsSource: 'idle',
49
- claudeModelsHasCurrent: true,
50
- claudeModelsLoading: false,
51
- codexModelsRequestSeq: 0,
52
- claudeModelsRequestSeq: 0,
53
- loading: true,
54
- initError: '',
55
- message: '',
56
- messageType: '',
57
- showAddModal: false,
58
- showEditModal: false,
59
- showModelModal: false,
60
- showModelListModal: false,
61
- showClaudeConfigModal: false,
62
- showEditConfigModal: false,
63
- showOpenclawConfigModal: false,
64
- showConfigTemplateModal: false,
65
- showAgentsModal: false,
66
- showSkillsModal: false,
67
- showHealthCheckModal: false,
68
- // Plugins
69
- pluginsActiveId: 'prompt-templates',
70
- pluginsLoading: false,
71
- pluginsError: '',
72
- promptTemplatesListRaw: [],
73
- promptTemplatesLoadedOnce: false,
74
- promptTemplatesKeyword: '',
75
- promptTemplateSelectedId: '',
76
- promptTemplateDraftRaw: null,
77
- promptTemplateVarValuesRaw: {},
78
- promptTemplatesMode: 'compose',
79
- promptComposerCommand: '',
80
- promptComposerPickerVisible: false,
81
- promptComposerPickerKeyword: '',
82
- promptComposerSelectedTemplateId: '',
83
- promptComposerVarValuesRaw: {},
84
- showPromptTemplateVarModal: false,
85
- promptTemplateVarDraftName: '',
86
- promptTemplateVarDraftError: '',
87
- showConfirmDialog: false,
88
- confirmDialogTitle: '',
89
- confirmDialogMessage: '',
90
- confirmDialogConfirmText: '确认',
91
- confirmDialogCancelText: '取消',
92
- confirmDialogDanger: false,
93
- confirmDialogConfirmDisabled: false,
94
- confirmDialogDisableWhen: null,
95
- confirmDialogResolver: null,
96
- configTemplateContent: '',
97
- configTemplateApplying: false,
98
- configTemplateDiffVisible: false,
99
- configTemplateDiffLoading: false,
100
- configTemplateDiffError: '',
101
- configTemplateDiffLines: [],
102
- configTemplateDiffStats: {
103
- added: 0,
104
- removed: 0,
105
- unchanged: 0
106
- },
107
- configTemplateDiffHasChangesValue: false,
108
- configTemplateDiffFingerprint: '',
109
- _configTemplateDiffPreviewRequestToken: null,
110
- configTemplateDiffConfirmEnabled: true,
111
- codexApplying: false,
112
- _pendingCodexApplyOptions: null,
113
- agentsContent: '',
114
- agentsPath: '',
115
- agentsPath: '',
116
- agentsExists: false,
117
- agentsLineEnding: '\n',
118
- agentsLoading: false,
119
- agentsSaving: false,
120
- agentsOriginalContent: '',
121
- agentsDiffVisible: false,
122
- agentsDiffLoading: false,
123
- agentsDiffError: '',
124
- agentsDiffLines: [],
125
- agentsDiffStats: {
126
- added: 0,
127
- removed: 0,
128
- unchanged: 0
129
- },
130
- agentsDiffTruncated: false,
131
- agentsDiffHasChangesValue: false,
132
- agentsDiffFingerprint: '',
133
- agentsContext: 'codex',
134
- agentsModalTitle: 'AGENTS.md 编辑器',
135
- agentsModalHint: '保存后会写入目标 AGENTS.md(与 config.toml 同级)。',
136
- skillsTargetApp: 'codex',
137
- skillsRootPath: '',
138
- skillsList: [],
139
- skillsSelectedNames: [],
140
- skillsLoading: false,
141
- skillsDeleting: false,
142
- skillsKeyword: '',
143
- skillsStatusFilter: 'all',
144
- skillsImportList: [],
145
- skillsImportSelectedKeys: [],
146
- skillsScanningImports: false,
147
- skillsImporting: false,
148
- skillsZipImporting: false,
149
- skillsExporting: false,
150
- skillsMarketLoading: false,
151
- skillsMarketLocalLoadedOnce: false,
152
- skillsMarketImportLoadedOnce: false,
153
- sessionPinnedMap: {},
154
- __mainTabSwitchState: {
155
- intent: '',
156
- pendingTarget: '',
157
- pendingConfigMode: '',
158
- ticket: 0
159
- },
160
- sessionsViewMode: 'browser',
161
- sessionsUsageTimeRange: '7d',
162
- sessionsUsageList: [],
163
- sessionsUsageLoadedOnce: false,
164
- sessionsUsageLoadedLimit: 0,
165
- sessionsUsageLoading: false,
166
- sessionsUsageError: '',
167
- sessionsList: [],
168
- sessionsLoadedOnce: false,
169
- sessionsLoading: false,
170
- sessionFilterSource: 'all',
171
- sessionPathFilter: '',
172
- sessionQuery: '',
173
- sessionRoleFilter: 'all',
174
- sessionTimePreset: 'all',
175
- sessionResumeWithYolo: true,
176
- sessionPathOptions: [],
177
- sessionPathOptionsLoading: false,
178
- sessionPathOptionsMap: {
179
- all: [],
180
- codex: [],
181
- claude: []
182
- },
183
- sessionPathOptionsLoadedMap: {
184
- all: false,
185
- codex: false,
186
- claude: false
187
- },
188
- sessionPathRequestSeqMap: {
189
- all: 0,
190
- codex: 0,
191
- claude: 0
192
- },
193
- sessionExporting: {},
194
- sessionCloning: {},
195
- sessionDeleting: {},
196
- activeSession: null,
197
- activeSessionMessages: [],
198
- activeSessionDetailError: '',
199
- activeSessionDetailClipped: false,
200
- sessionDetailLoading: false,
201
- sessionDetailRequestSeq: 0,
202
- sessionDetailInitialMessageLimit: 80,
203
- sessionDetailFetchStep: 80,
204
- sessionDetailMessageLimit: 80,
205
- sessionDetailMessageLimitCap: 1000,
206
- sessionTimelineActiveKey: '',
207
- sessionTimelineRafId: 0,
208
- sessionTimelineLastSyncAt: 0,
209
- sessionTimelineLastScrollTop: 0,
210
- sessionTimelineLastAnchorY: 0,
211
- sessionTimelineLastDirection: 0,
212
- sessionTimelineEnabled: true,
213
- sessionMessageRefMap: Object.create(null),
214
- sessionMessageRefBinderMap: Object.create(null),
215
- sessionPreviewScrollEl: null,
216
- sessionPreviewContainerEl: null,
217
- sessionPreviewHeaderEl: null,
218
- sessionPreviewHeaderResizeObserver: null,
219
- sessionListRenderEnabled: false,
220
- sessionListVisibleCount: 0,
221
- sessionListInitialBatchSize: 20,
222
- sessionListLoadStep: 40,
223
- sessionPreviewRenderEnabled: false,
224
- sessionTabRenderTicket: 0,
225
- sessionPreviewVisibleCount: 0,
226
- sessionPreviewInitialBatchSize: 12,
227
- sessionPreviewLoadStep: 24,
228
- sessionPreviewPendingVisibleCount: 0,
229
- sessionPreviewLoadingMore: false,
230
- sessionStandalone: false,
231
- sessionStandaloneError: '',
232
- sessionStandaloneText: '',
233
- sessionStandaloneTitle: '',
234
- sessionStandaloneSourceLabel: '',
235
- sessionStandaloneLoading: false,
236
- sessionStandaloneRequestSeq: 0,
237
- speedResults: {},
238
- speedLoading: {},
239
- claudeSpeedResults: {},
240
- claudeSpeedLoading: {},
241
- claudeShareLoading: {},
242
- providerShareLoading: {},
243
- shareCommandPrefix: 'npm start',
244
- providerSwitchInProgress: false,
245
- pendingProviderSwitch: '',
246
- providerSwitchDisplayTarget: '',
247
- healthCheckBatchTotal: 0,
248
- healthCheckBatchDone: 0,
249
- healthCheckBatchFailed: 0,
250
- installPackageManager: 'npm',
251
- installCommandAction: 'install',
252
- installRegistryPreset: 'default',
253
- installRegistryCustom: '',
254
- installStatusTargets: null,
255
- newProvider: { name: '', url: '', key: '', useTransform: false },
256
- resetConfigLoading: false,
257
- editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false },
258
- newModelName: '',
259
- currentClaudeConfig: '',
260
- currentClaudeModel: '',
261
- editingConfig: { name: '', apiKey: '', baseUrl: '', model: '' },
262
- claudeConfigs: {
263
- '智谱GLM': {
264
- apiKey: '',
265
- baseUrl: 'https://open.bigmodel.cn/api/anthropic',
266
- model: 'glm-4.7',
267
- hasKey: false
268
- }
269
- },
270
- newClaudeConfig: {
271
- name: '',
272
- apiKey: '',
273
- baseUrl: 'https://open.bigmodel.cn/api/anthropic',
274
- model: 'glm-4.7'
275
- },
276
- currentOpenclawConfig: '',
277
- openclawConfigs: {
278
- '默认配置': {
279
- content: DEFAULT_OPENCLAW_TEMPLATE
280
- }
281
- },
282
- openclawEditing: { name: '', content: '', lockName: false },
283
- openclawEditorTitle: '添加 OpenClaw 配置',
284
- openclawConfigPath: '',
285
- openclawConfigExists: false,
286
- openclawLineEnding: '\n',
287
- openclawAuthProfilesByProvider: {},
288
- openclawPendingAuthProfileUpdates: {},
289
- openclawFileLoading: false,
290
- openclawSaving: false,
291
- openclawApplying: false,
292
- openclawWorkspaceFileName: 'SOUL.md',
293
- agentsWorkspaceFileName: '',
294
- openclawStructured: {
295
- agentPrimary: '',
296
- agentFallbacks: [],
297
- workspace: '',
298
- timeout: '',
299
- contextTokens: '',
300
- maxConcurrent: '',
301
- envItems: [],
302
- toolsProfile: 'default',
303
- toolsAllow: [],
304
- toolsDeny: []
305
- },
306
- openclawQuick: {
307
- providerName: '',
308
- baseUrl: '',
309
- baseUrlReadOnly: false,
310
- baseUrlDisplayKind: 'missing',
311
- apiKey: '',
312
- apiKeyReadOnly: false,
313
- apiKeyDisplayKind: 'missing',
314
- apiKeySourceKind: '',
315
- apiKeySourceProfileId: '',
316
- apiKeySourceWriteField: '',
317
- apiKeySourceOriginalValue: '',
318
- apiKeySourceCredentialType: '',
319
- apiType: 'openai-responses',
320
- modelId: '',
321
- modelName: '',
322
- contextWindow: '',
323
- maxTokens: '',
324
- setPrimary: true,
325
- overrideProvider: true,
326
- overrideModels: true,
327
- showKey: false
328
- },
329
- openclawAgentsList: [],
330
- openclawProviders: [],
331
- openclawMissingProviders: [],
332
- healthCheckLoading: false,
333
- healthCheckResult: null,
334
- healthCheckRemote: false,
335
- claudeDownloadLoading: false,
336
- claudeDownloadProgress: 0,
337
- claudeDownloadTimer: null,
338
- codexDownloadLoading: false,
339
- codexDownloadProgress: 0,
340
- codexDownloadTimer: null,
341
- settingsTab: 'backup',
342
- sessionTrashEnabled: true,
343
- sessionTrashItems: [],
344
- sessionTrashVisibleCount: SESSION_TRASH_PAGE_SIZE,
345
- sessionTrashTotalCount: 0,
346
- sessionTrashCountLoadedOnce: false,
347
- sessionTrashLoadedOnce: false,
348
- sessionTrashLastLoadFailed: false,
349
- sessionTrashCountRequestToken: 0,
350
- sessionTrashListRequestToken: 0,
351
- sessionTrashCountPendingOptions: null,
352
- sessionTrashPendingOptions: null,
353
- sessionTrashCountLoading: false,
354
- sessionTrashLoading: false,
355
- sessionTrashRestoring: {},
356
- sessionTrashPurging: {},
357
- sessionTrashClearing: false,
358
- claudeImportLoading: false,
359
- codexImportLoading: false,
360
- codexAuthProfiles: [],
361
- forceCompactLayout: false,
362
- taskOrchestrationTabEnabled: true,
363
- taskOrchestration: {
364
- loading: false,
365
- planning: false,
366
- running: false,
367
- queueAdding: false,
368
- queueStarting: false,
369
- retrying: false,
370
- target: '',
371
- title: '',
372
- notes: '',
373
- followUpsText: '',
374
- workflowIdsText: '',
375
- selectedEngine: 'codex',
376
- runMode: 'write',
377
- concurrency: 2,
378
- autoFixRounds: 1,
379
- plan: null,
380
- planFingerprint: '',
381
- planIssues: [],
382
- planWarnings: [],
383
- overviewWarnings: [],
384
- workflows: [],
385
- queue: [],
386
- runs: [],
387
- selectedRunId: '',
388
- workspaceTab: 'queue',
389
- selectedRunDetail: null,
390
- selectedRunLoading: false,
391
- selectedRunError: '',
392
- detailRequestToken: 0,
393
- lastLoadedAt: '',
394
- lastError: ''
395
- },
396
- _taskOrchestrationPollTimer: 0
397
- };
398
- },
399
-
400
- mounted() {
401
- if (typeof this.initI18n === 'function') {
402
- this.initI18n();
403
- }
404
- if (typeof this.t === 'function') {
405
- this.confirmDialogConfirmText = this.t('confirm.ok');
406
- this.confirmDialogCancelText = this.t('confirm.cancel');
407
- this.agentsModalTitle = this.t('modal.agents.title');
408
- this.agentsModalHint = this.t('modal.agents.hint');
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
- }
459
- this.initSessionStandalone();
460
- this.updateCompactLayoutMode();
461
- if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
462
- this.mainTab = 'config';
463
- }
464
- const savedSessionYolo = localStorage.getItem('codexmateSessionResumeYolo');
465
- if (savedSessionYolo === '0' || savedSessionYolo === 'false') {
466
- this.sessionResumeWithYolo = false;
467
- } else if (savedSessionYolo === '1' || savedSessionYolo === 'true') {
468
- this.sessionResumeWithYolo = true;
469
- }
470
- this.restoreSessionFilterCache();
471
- this.restoreSessionPinnedMap();
472
- this.shareCommandPrefix = this.normalizeShareCommandPrefix(localStorage.getItem('codexmateShareCommandPrefix'));
473
- this.sessionTrashEnabled = this.normalizeSessionTrashEnabled(localStorage.getItem('codexmateSessionTrashEnabled'));
474
- this.configTemplateDiffConfirmEnabled = loadConfigTemplateDiffConfirmEnabledFromStorage(localStorage);
475
- window.addEventListener('resize', this.onWindowResize);
476
- window.addEventListener('keydown', this.handleGlobalKeydown);
477
- window.addEventListener('beforeunload', this.handleBeforeUnload);
478
- const savedConfigs = localStorage.getItem('claudeConfigs');
479
- if (savedConfigs) {
480
- try {
481
- this.claudeConfigs = JSON.parse(savedConfigs);
482
- for (const [name, config] of Object.entries(this.claudeConfigs)) {
483
- if (config.apiKey && config.apiKey.includes('****')) {
484
- config.apiKey = '';
485
- config.hasKey = false;
486
- }
487
- }
488
- localStorage.setItem('claudeConfigs', JSON.stringify(this.claudeConfigs));
489
- } catch (e) {
490
- console.error('加载 Claude 配置失败:', e);
491
- }
492
- }
493
- const normalizeOpenclawConfigs = (configs) => {
494
- const source = configs && typeof configs === 'object' && !Array.isArray(configs)
495
- ? configs
496
- : {};
497
- const defaultEntry = source['默认配置']
498
- && typeof source['默认配置'] === 'object'
499
- && !Array.isArray(source['默认配置'])
500
- ? source['默认配置']
501
- : { content: DEFAULT_OPENCLAW_TEMPLATE };
502
- const normalized = {
503
- '默认配置': {
504
- content: typeof defaultEntry.content === 'string' ? defaultEntry.content : DEFAULT_OPENCLAW_TEMPLATE
505
- }
506
- };
507
- for (const [name, value] of Object.entries(source)) {
508
- if (name === '默认配置') continue;
509
- normalized[name] = value;
510
- }
511
- return normalized;
512
- };
513
- const savedOpenclawConfigs = localStorage.getItem('openclawConfigs');
514
- if (savedOpenclawConfigs) {
515
- try {
516
- this.openclawConfigs = normalizeOpenclawConfigs(JSON.parse(savedOpenclawConfigs));
517
- } catch (e) {
518
- console.error('加载 OpenClaw 配置失败:', e);
519
- this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
520
- }
521
- } else {
522
- this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
523
- }
524
- const configNames = Object.keys(this.openclawConfigs);
525
- if (configNames.length > 0) {
526
- this.currentOpenclawConfig = this.openclawConfigs['默认配置'] ? '默认配置' : configNames[0];
527
- }
528
- const runInitialLoad = () => {
529
- const triggerLoad = async () => {
530
- this._initialLoadTimer = 0;
531
- const startupOk = await this.loadAll();
532
- if (!startupOk) {
533
- return;
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
- }
543
- void this.refreshClaudeSelectionFromSettings({ silent: true });
544
- void this.syncDefaultOpenclawConfigEntry({ silent: true });
545
- };
546
- if (typeof requestAnimationFrame === 'function') {
547
- this._initialLoadRafId = requestAnimationFrame(() => {
548
- this._initialLoadRafId = 0;
549
- if (typeof setTimeout === 'function') {
550
- this._initialLoadTimer = setTimeout(triggerLoad, 120);
551
- return;
552
- }
553
- triggerLoad();
554
- });
555
- return;
556
- }
557
- if (typeof setTimeout === 'function') {
558
- this._initialLoadTimer = setTimeout(triggerLoad, 120);
559
- return;
560
- }
561
- triggerLoad();
562
- };
563
- if (document.readyState === 'complete') {
564
- runInitialLoad();
565
- } else {
566
- this._initialLoadOnWindowLoad = () => {
567
- if (typeof window !== 'undefined' && typeof window.removeEventListener === 'function') {
568
- window.removeEventListener('load', this._initialLoadOnWindowLoad);
569
- }
570
- this._initialLoadOnWindowLoad = null;
571
- runInitialLoad();
572
- };
573
- window.addEventListener('load', this._initialLoadOnWindowLoad, { once: true });
574
- }
575
- },
576
-
577
- beforeUnmount() {
578
- this.teardownSessionTabRender();
579
- this.cancelScheduledSessionTabDeferredTeardown();
580
- this.disconnectSessionPreviewHeaderResizeObserver();
581
- if (this._initialLoadOnWindowLoad) {
582
- window.removeEventListener('load', this._initialLoadOnWindowLoad);
583
- this._initialLoadOnWindowLoad = null;
584
- }
585
- if (this._initialLoadRafId) {
586
- cancelAnimationFrame(this._initialLoadRafId);
587
- this._initialLoadRafId = 0;
588
- }
589
- if (this._initialLoadTimer) {
590
- clearTimeout(this._initialLoadTimer);
591
- this._initialLoadTimer = 0;
592
- }
593
- window.removeEventListener('resize', this.onWindowResize);
594
- window.removeEventListener('keydown', this.handleGlobalKeydown);
595
- window.removeEventListener('beforeunload', this.handleBeforeUnload);
596
- this.applyCompactLayoutClass(false);
597
- this.stopTaskOrchestrationPolling();
598
- this.sessionPreviewScrollEl = null;
599
- this.sessionPreviewContainerEl = null;
600
- this.sessionPreviewHeaderEl = null;
601
- this.clearSessionTimelineRefs();
602
- },
603
-
604
- computed: createAppComputed(),
605
- methods: createAppMethods()
606
- });
607
-
608
- app.mount('#app');
609
- });
1
+ import {
2
+ DEFAULT_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
3
+ DEFAULT_MODEL_CONTEXT_WINDOW,
4
+ DEFAULT_OPENCLAW_TEMPLATE,
5
+ SESSION_TRASH_PAGE_SIZE
6
+ } from './modules/app.constants.mjs';
7
+ import { createAppComputed } from './modules/app.computed.index.mjs';
8
+ import { createAppMethods } from './modules/app.methods.index.mjs';
9
+ import { loadConfigTemplateDiffConfirmEnabledFromStorage } from './modules/config-template-confirm-pref.mjs';
10
+
11
+ document.addEventListener('DOMContentLoaded', () => {
12
+ if (typeof Vue === 'undefined') {
13
+ console.error('Vue 库未能在 DOMContentLoaded 触发前加载完成。');
14
+ const fallbackTarget = document.querySelector('#app') || document.querySelector('[v-cloak]');
15
+ if (fallbackTarget) {
16
+ fallbackTarget.removeAttribute('v-cloak');
17
+ fallbackTarget.classList.remove('v-cloak');
18
+ fallbackTarget.innerHTML = '';
19
+ const notice = document.createElement('div');
20
+ notice.className = 'fallback-message';
21
+ notice.textContent = 'Web UI 加载失败:Vue 未加载。请检查网络或刷新页面。';
22
+ fallbackTarget.appendChild(notice);
23
+ }
24
+ return;
25
+ }
26
+
27
+ const { createApp } = Vue;
28
+
29
+ const app = createApp({
30
+ data() {
31
+ return {
32
+ lang: 'zh',
33
+ mainTab: 'dashboard',
34
+ configMode: 'codex',
35
+ currentProvider: '',
36
+ currentModel: '',
37
+ serviceTier: 'fast',
38
+ modelReasoningEffort: 'medium',
39
+ modelContextWindowInput: String(DEFAULT_MODEL_CONTEXT_WINDOW),
40
+ modelAutoCompactTokenLimitInput: String(DEFAULT_MODEL_AUTO_COMPACT_TOKEN_LIMIT),
41
+ editingCodexBudgetField: '',
42
+ providersList: [],
43
+ models: [],
44
+ codexModelsLoading: false,
45
+ modelsSource: 'remote',
46
+ modelsHasCurrent: true,
47
+ claudeModels: [],
48
+ claudeModelsSource: 'idle',
49
+ claudeModelsHasCurrent: true,
50
+ claudeModelsLoading: false,
51
+ codexModelsRequestSeq: 0,
52
+ claudeModelsRequestSeq: 0,
53
+ loading: true,
54
+ initError: '',
55
+ message: '',
56
+ messageType: '',
57
+ showAddModal: false,
58
+ showEditModal: false,
59
+ showModelModal: false,
60
+ showModelListModal: false,
61
+ showClaudeConfigModal: false,
62
+ showEditConfigModal: false,
63
+ showOpenclawConfigModal: false,
64
+ showConfigTemplateModal: false,
65
+ showAgentsModal: false,
66
+ showSkillsModal: false,
67
+ showHealthCheckModal: false,
68
+ // Plugins
69
+ pluginsActiveId: 'prompt-templates',
70
+ pluginsLoading: false,
71
+ pluginsError: '',
72
+ promptTemplatesListRaw: [],
73
+ promptTemplatesLoadedOnce: false,
74
+ promptTemplatesKeyword: '',
75
+ promptTemplateSelectedId: '',
76
+ promptTemplateDraftRaw: null,
77
+ promptTemplateVarValuesRaw: {},
78
+ promptTemplatesMode: 'compose',
79
+ promptComposerCommand: '',
80
+ promptComposerPickerVisible: false,
81
+ promptComposerPickerKeyword: '',
82
+ promptComposerSelectedTemplateId: '',
83
+ promptComposerVarValuesRaw: {},
84
+ showPromptTemplateVarModal: false,
85
+ promptTemplateVarDraftName: '',
86
+ promptTemplateVarDraftError: '',
87
+ showConfirmDialog: false,
88
+ confirmDialogTitle: '',
89
+ confirmDialogMessage: '',
90
+ confirmDialogConfirmText: '确认',
91
+ confirmDialogCancelText: '取消',
92
+ confirmDialogDanger: false,
93
+ confirmDialogConfirmDisabled: false,
94
+ confirmDialogDisableWhen: null,
95
+ confirmDialogResolver: null,
96
+ configTemplateContent: '',
97
+ configTemplateApplying: false,
98
+ configTemplateDiffVisible: false,
99
+ configTemplateDiffLoading: false,
100
+ configTemplateDiffError: '',
101
+ configTemplateDiffLines: [],
102
+ configTemplateDiffStats: {
103
+ added: 0,
104
+ removed: 0,
105
+ unchanged: 0
106
+ },
107
+ configTemplateDiffHasChangesValue: false,
108
+ configTemplateDiffFingerprint: '',
109
+ _configTemplateDiffPreviewRequestToken: null,
110
+ configTemplateDiffConfirmEnabled: true,
111
+ codexApplying: false,
112
+ _pendingCodexApplyOptions: null,
113
+ agentsContent: '',
114
+ agentsPath: '',
115
+ agentsPath: '',
116
+ agentsExists: false,
117
+ agentsLineEnding: '\n',
118
+ agentsLoading: false,
119
+ agentsSaving: false,
120
+ agentsOriginalContent: '',
121
+ agentsDiffVisible: false,
122
+ agentsDiffLoading: false,
123
+ agentsDiffError: '',
124
+ agentsDiffLines: [],
125
+ agentsDiffStats: {
126
+ added: 0,
127
+ removed: 0,
128
+ unchanged: 0
129
+ },
130
+ agentsDiffTruncated: false,
131
+ agentsDiffHasChangesValue: false,
132
+ agentsDiffFingerprint: '',
133
+ agentsContext: 'codex',
134
+ agentsModalTitle: 'AGENTS.md 编辑器',
135
+ agentsModalHint: '保存后会写入目标 AGENTS.md(与 config.toml 同级)。',
136
+ skillsTargetApp: 'codex',
137
+ skillsRootPath: '',
138
+ skillsList: [],
139
+ skillsSelectedNames: [],
140
+ skillsLoading: false,
141
+ skillsDeleting: false,
142
+ skillsKeyword: '',
143
+ skillsStatusFilter: 'all',
144
+ skillsImportList: [],
145
+ skillsImportSelectedKeys: [],
146
+ skillsScanningImports: false,
147
+ skillsImporting: false,
148
+ skillsZipImporting: false,
149
+ skillsExporting: false,
150
+ skillsMarketLoading: false,
151
+ skillsMarketLocalLoadedOnce: false,
152
+ skillsMarketImportLoadedOnce: false,
153
+ sessionPinnedMap: {},
154
+ __mainTabSwitchState: {
155
+ intent: '',
156
+ pendingTarget: '',
157
+ pendingConfigMode: '',
158
+ ticket: 0
159
+ },
160
+ sessionsViewMode: 'browser',
161
+ sessionsUsageTimeRange: '7d',
162
+ sessionsUsageList: [],
163
+ sessionsUsageCompareEnabled: false,
164
+ sessionsUsageSelectedDayKey: '',
165
+ sessionsUsageLoadedOnce: false,
166
+ sessionsUsageLoadedLimit: 0,
167
+ sessionsUsageLoading: false,
168
+ sessionsUsageError: '',
169
+ sessionsList: [],
170
+ sessionsLoadedOnce: false,
171
+ sessionsLoading: false,
172
+ sessionFilterSource: 'all',
173
+ sessionPathFilter: '',
174
+ sessionQuery: '',
175
+ sessionRoleFilter: 'all',
176
+ sessionTimePreset: 'all',
177
+ sessionSortMode: 'time',
178
+ sessionResumeWithYolo: true,
179
+ sessionPathOptions: [],
180
+ sessionPathOptionsLoading: false,
181
+ sessionPathOptionsMap: {
182
+ all: [],
183
+ codex: [],
184
+ claude: [],
185
+ gemini: []
186
+ },
187
+ sessionPathOptionsLoadedMap: {
188
+ all: false,
189
+ codex: false,
190
+ claude: false,
191
+ gemini: false
192
+ },
193
+ sessionPathRequestSeqMap: {
194
+ all: 0,
195
+ codex: 0,
196
+ claude: 0,
197
+ gemini: 0
198
+ },
199
+ sessionExporting: {},
200
+ sessionConverting: {},
201
+ sessionCloning: {},
202
+ sessionDeleting: {},
203
+ activeSession: null,
204
+ activeSessionMessages: [],
205
+ activeSessionDetailError: '',
206
+ activeSessionDetailClipped: false,
207
+ sessionDetailLoading: false,
208
+ sessionDetailRequestSeq: 0,
209
+ sessionDetailInitialMessageLimit: 80,
210
+ sessionDetailFetchStep: 80,
211
+ sessionDetailMessageLimit: 80,
212
+ sessionDetailMessageLimitCap: 1000,
213
+ sessionTimelineActiveKey: '',
214
+ sessionTimelineRafId: 0,
215
+ sessionTimelineLastSyncAt: 0,
216
+ sessionTimelineLastScrollTop: 0,
217
+ sessionTimelineLastAnchorY: 0,
218
+ sessionTimelineLastDirection: 0,
219
+ sessionTimelineEnabled: true,
220
+ sessionMessageRefMap: Object.create(null),
221
+ sessionMessageRefBinderMap: Object.create(null),
222
+ sessionPreviewScrollEl: null,
223
+ sessionPreviewContainerEl: null,
224
+ sessionPreviewHeaderEl: null,
225
+ sessionPreviewHeaderResizeObserver: null,
226
+ sessionListRenderEnabled: false,
227
+ sessionListVisibleCount: 0,
228
+ sessionListInitialBatchSize: 20,
229
+ sessionListLoadStep: 40,
230
+ sessionPreviewRenderEnabled: false,
231
+ sessionTabRenderTicket: 0,
232
+ sessionPreviewVisibleCount: 0,
233
+ sessionPreviewInitialBatchSize: 12,
234
+ sessionPreviewLoadStep: 24,
235
+ sessionPreviewPendingVisibleCount: 0,
236
+ sessionPreviewLoadingMore: false,
237
+ sessionStandalone: false,
238
+ sessionStandaloneError: '',
239
+ sessionStandaloneText: '',
240
+ sessionStandaloneTitle: '',
241
+ sessionStandaloneSourceLabel: '',
242
+ sessionStandaloneLoading: false,
243
+ sessionStandaloneRequestSeq: 0,
244
+ speedResults: {},
245
+ speedLoading: {},
246
+ claudeSpeedResults: {},
247
+ claudeSpeedLoading: {},
248
+ claudeShareLoading: {},
249
+ providerShareLoading: {},
250
+ shareCommandPrefix: 'npm start',
251
+ providerSwitchInProgress: false,
252
+ pendingProviderSwitch: '',
253
+ providerSwitchDisplayTarget: '',
254
+ healthCheckBatchTotal: 0,
255
+ healthCheckBatchDone: 0,
256
+ healthCheckBatchFailed: 0,
257
+ installPackageManager: 'npm',
258
+ installCommandAction: 'install',
259
+ installRegistryPreset: 'default',
260
+ installRegistryCustom: '',
261
+ installStatusTargets: null,
262
+ newProvider: { name: '', url: '', key: '', useTransform: false },
263
+ resetConfigLoading: false,
264
+ editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false },
265
+ newModelName: '',
266
+ currentClaudeConfig: '',
267
+ currentClaudeModel: '',
268
+ claudeCustomModelDraft: '',
269
+ editingConfig: { name: '', apiKey: '', baseUrl: '', model: '' },
270
+ claudeConfigs: {
271
+ '智谱GLM': {
272
+ apiKey: '',
273
+ baseUrl: 'https://open.bigmodel.cn/api/anthropic',
274
+ model: 'glm-4.7',
275
+ hasKey: false
276
+ }
277
+ },
278
+ newClaudeConfig: {
279
+ name: '',
280
+ apiKey: '',
281
+ baseUrl: 'https://open.bigmodel.cn/api/anthropic',
282
+ model: 'glm-4.7'
283
+ },
284
+ currentOpenclawConfig: '',
285
+ openclawConfigs: {
286
+ '默认配置': {
287
+ content: DEFAULT_OPENCLAW_TEMPLATE
288
+ }
289
+ },
290
+ openclawEditing: { name: '', content: '', lockName: false },
291
+ openclawEditorTitle: '添加 OpenClaw 配置',
292
+ openclawConfigPath: '',
293
+ openclawConfigExists: false,
294
+ openclawLineEnding: '\n',
295
+ openclawAuthProfilesByProvider: {},
296
+ openclawPendingAuthProfileUpdates: {},
297
+ openclawFileLoading: false,
298
+ openclawSaving: false,
299
+ openclawApplying: false,
300
+ openclawWorkspaceFileName: 'SOUL.md',
301
+ agentsWorkspaceFileName: '',
302
+ openclawStructured: {
303
+ agentPrimary: '',
304
+ agentFallbacks: [],
305
+ workspace: '',
306
+ timeout: '',
307
+ contextTokens: '',
308
+ maxConcurrent: '',
309
+ envItems: [],
310
+ toolsProfile: 'default',
311
+ toolsAllow: [],
312
+ toolsDeny: []
313
+ },
314
+ openclawQuick: {
315
+ providerName: '',
316
+ baseUrl: '',
317
+ baseUrlReadOnly: false,
318
+ baseUrlDisplayKind: 'missing',
319
+ apiKey: '',
320
+ apiKeyReadOnly: false,
321
+ apiKeyDisplayKind: 'missing',
322
+ apiKeySourceKind: '',
323
+ apiKeySourceProfileId: '',
324
+ apiKeySourceWriteField: '',
325
+ apiKeySourceOriginalValue: '',
326
+ apiKeySourceCredentialType: '',
327
+ apiType: 'openai-responses',
328
+ modelId: '',
329
+ modelName: '',
330
+ contextWindow: '',
331
+ maxTokens: '',
332
+ setPrimary: true,
333
+ overrideProvider: true,
334
+ overrideModels: true,
335
+ showKey: false
336
+ },
337
+ openclawAgentsList: [],
338
+ openclawProviders: [],
339
+ openclawMissingProviders: [],
340
+ healthCheckLoading: false,
341
+ healthCheckResult: null,
342
+ healthCheckRemote: false,
343
+ claudeDownloadLoading: false,
344
+ claudeDownloadProgress: 0,
345
+ claudeDownloadTimer: null,
346
+ codexDownloadLoading: false,
347
+ codexDownloadProgress: 0,
348
+ codexDownloadTimer: null,
349
+ settingsTab: 'backup',
350
+ sessionTrashEnabled: true,
351
+ sessionTrashItems: [],
352
+ sessionTrashVisibleCount: SESSION_TRASH_PAGE_SIZE,
353
+ sessionTrashTotalCount: 0,
354
+ sessionTrashCountLoadedOnce: false,
355
+ sessionTrashLoadedOnce: false,
356
+ sessionTrashLastLoadFailed: false,
357
+ sessionTrashCountRequestToken: 0,
358
+ sessionTrashListRequestToken: 0,
359
+ sessionTrashCountPendingOptions: null,
360
+ sessionTrashPendingOptions: null,
361
+ sessionTrashCountLoading: false,
362
+ sessionTrashLoading: false,
363
+ sessionTrashRestoring: {},
364
+ sessionTrashPurging: {},
365
+ sessionTrashClearing: false,
366
+ claudeImportLoading: false,
367
+ codexImportLoading: false,
368
+ codexAuthProfiles: [],
369
+ forceCompactLayout: false,
370
+ taskOrchestrationTabEnabled: true,
371
+ taskOrchestration: {
372
+ loading: false,
373
+ planning: false,
374
+ running: false,
375
+ queueAdding: false,
376
+ queueStarting: false,
377
+ retrying: false,
378
+ target: '',
379
+ title: '',
380
+ notes: '',
381
+ followUpsText: '',
382
+ workflowIdsText: '',
383
+ selectedEngine: 'codex',
384
+ runMode: 'write',
385
+ concurrency: 2,
386
+ autoFixRounds: 1,
387
+ plan: null,
388
+ planFingerprint: '',
389
+ planIssues: [],
390
+ planWarnings: [],
391
+ overviewWarnings: [],
392
+ workflows: [],
393
+ queue: [],
394
+ runs: [],
395
+ selectedRunId: '',
396
+ workspaceTab: 'queue',
397
+ selectedRunDetail: null,
398
+ selectedRunLoading: false,
399
+ selectedRunError: '',
400
+ detailRequestToken: 0,
401
+ lastLoadedAt: '',
402
+ lastError: ''
403
+ },
404
+ _taskOrchestrationPollTimer: 0
405
+ };
406
+ },
407
+
408
+ mounted() {
409
+ if (typeof this.initI18n === 'function') {
410
+ this.initI18n();
411
+ }
412
+ if (typeof this.t === 'function') {
413
+ this.confirmDialogConfirmText = this.t('confirm.ok');
414
+ this.confirmDialogCancelText = this.t('confirm.cancel');
415
+ this.agentsModalTitle = this.t('modal.agents.title');
416
+ this.agentsModalHint = this.t('modal.agents.hint');
417
+ }
418
+ {
419
+ const NAV_STATE_STORAGE_KEY = 'codexmateNavState.v1';
420
+ const mainTabSet = new Set(['dashboard', 'config', 'sessions', 'usage', 'orchestration', 'market', 'plugins', 'docs', 'settings']);
421
+ let restored = null;
422
+ try {
423
+ const raw = localStorage.getItem(NAV_STATE_STORAGE_KEY) || '';
424
+ restored = raw ? JSON.parse(raw) : null;
425
+ } catch (_) {
426
+ restored = null;
427
+ }
428
+ const nextMainTab = restored && typeof restored.mainTab === 'string'
429
+ ? restored.mainTab.trim().toLowerCase()
430
+ : '';
431
+ const nextConfigMode = restored && typeof restored.configMode === 'string'
432
+ ? restored.configMode.trim().toLowerCase()
433
+ : '';
434
+ let urlMainTab = '';
435
+ try {
436
+ const url = new URL(window.location.href);
437
+ if (url.pathname !== '/session') {
438
+ urlMainTab = String(url.searchParams.get('tab') || '').trim().toLowerCase();
439
+ }
440
+ } catch (_) {
441
+ urlMainTab = '';
442
+ }
443
+ const resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab)
444
+ ? urlMainTab
445
+ : nextMainTab;
446
+ if (nextConfigMode && typeof this.switchConfigMode === 'function') {
447
+ this.__navStateRestoring = true;
448
+ try {
449
+ if (nextConfigMode === 'codex' || nextConfigMode === 'claude' || nextConfigMode === 'openclaw') {
450
+ this.configMode = nextConfigMode;
451
+ }
452
+ if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
453
+ this.switchMainTab(resolvedMainTab);
454
+ }
455
+ } finally {
456
+ this.__navStateRestoring = false;
457
+ }
458
+ } else if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
459
+ this.__navStateRestoring = true;
460
+ try {
461
+ this.switchMainTab(resolvedMainTab);
462
+ } finally {
463
+ this.__navStateRestoring = false;
464
+ }
465
+ }
466
+ }
467
+ this.initSessionStandalone();
468
+ this.updateCompactLayoutMode();
469
+ if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
470
+ this.mainTab = 'config';
471
+ }
472
+ const savedSessionYolo = localStorage.getItem('codexmateSessionResumeYolo');
473
+ if (savedSessionYolo === '0' || savedSessionYolo === 'false') {
474
+ this.sessionResumeWithYolo = false;
475
+ } else if (savedSessionYolo === '1' || savedSessionYolo === 'true') {
476
+ this.sessionResumeWithYolo = true;
477
+ }
478
+ this.restoreSessionFilterCache();
479
+ this.restoreSessionPinnedMap();
480
+ this.shareCommandPrefix = this.normalizeShareCommandPrefix(localStorage.getItem('codexmateShareCommandPrefix'));
481
+ this.sessionTrashEnabled = this.normalizeSessionTrashEnabled(localStorage.getItem('codexmateSessionTrashEnabled'));
482
+ this.configTemplateDiffConfirmEnabled = loadConfigTemplateDiffConfirmEnabledFromStorage(localStorage);
483
+ window.addEventListener('resize', this.onWindowResize);
484
+ window.addEventListener('keydown', this.handleGlobalKeydown);
485
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
486
+ const savedConfigs = localStorage.getItem('claudeConfigs');
487
+ if (savedConfigs) {
488
+ try {
489
+ this.claudeConfigs = JSON.parse(savedConfigs);
490
+ for (const [name, config] of Object.entries(this.claudeConfigs)) {
491
+ if (config.apiKey && config.apiKey.includes('****')) {
492
+ config.apiKey = '';
493
+ config.hasKey = false;
494
+ }
495
+ }
496
+ localStorage.setItem('claudeConfigs', JSON.stringify(this.claudeConfigs));
497
+ } catch (e) {
498
+ console.error('加载 Claude 配置失败:', e);
499
+ }
500
+ }
501
+ if (!this.currentClaudeConfig) {
502
+ const claudeConfigNames = Object.keys(this.claudeConfigs || {});
503
+ if (claudeConfigNames.length > 0) {
504
+ this.currentClaudeConfig = claudeConfigNames[0];
505
+ const initialClaudeConfig = this.claudeConfigs[this.currentClaudeConfig];
506
+ this.currentClaudeModel = initialClaudeConfig && initialClaudeConfig.model ? initialClaudeConfig.model : '';
507
+ }
508
+ }
509
+ const normalizeOpenclawConfigs = (configs) => {
510
+ const source = configs && typeof configs === 'object' && !Array.isArray(configs)
511
+ ? configs
512
+ : {};
513
+ const defaultEntry = source['默认配置']
514
+ && typeof source['默认配置'] === 'object'
515
+ && !Array.isArray(source['默认配置'])
516
+ ? source['默认配置']
517
+ : { content: DEFAULT_OPENCLAW_TEMPLATE };
518
+ const normalized = {
519
+ '默认配置': {
520
+ content: typeof defaultEntry.content === 'string' ? defaultEntry.content : DEFAULT_OPENCLAW_TEMPLATE
521
+ }
522
+ };
523
+ for (const [name, value] of Object.entries(source)) {
524
+ if (name === '默认配置') continue;
525
+ normalized[name] = value;
526
+ }
527
+ return normalized;
528
+ };
529
+ const savedOpenclawConfigs = localStorage.getItem('openclawConfigs');
530
+ if (savedOpenclawConfigs) {
531
+ try {
532
+ this.openclawConfigs = normalizeOpenclawConfigs(JSON.parse(savedOpenclawConfigs));
533
+ } catch (e) {
534
+ console.error('加载 OpenClaw 配置失败:', e);
535
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
536
+ }
537
+ } else {
538
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
539
+ }
540
+ const configNames = Object.keys(this.openclawConfigs);
541
+ if (configNames.length > 0) {
542
+ this.currentOpenclawConfig = this.openclawConfigs['默认配置'] ? '默认配置' : configNames[0];
543
+ }
544
+ const runInitialLoad = () => {
545
+ const triggerLoad = async () => {
546
+ this._initialLoadTimer = 0;
547
+ const startupOk = await this.loadAll();
548
+ if (!startupOk) {
549
+ return;
550
+ }
551
+ if (this.mainTab === 'dashboard') {
552
+ if (!this.__doctorLoadedOnce) {
553
+ this.__doctorLoadedOnce = true;
554
+ if (typeof this.runHealthCheck === 'function') {
555
+ void this.runHealthCheck({ doctor: true, silent: true });
556
+ }
557
+ }
558
+ }
559
+ void this.refreshClaudeSelectionFromSettings({ silent: true });
560
+ void this.syncDefaultOpenclawConfigEntry({ silent: true });
561
+ };
562
+ if (typeof requestAnimationFrame === 'function') {
563
+ this._initialLoadRafId = requestAnimationFrame(() => {
564
+ this._initialLoadRafId = 0;
565
+ if (typeof setTimeout === 'function') {
566
+ this._initialLoadTimer = setTimeout(triggerLoad, 120);
567
+ return;
568
+ }
569
+ triggerLoad();
570
+ });
571
+ return;
572
+ }
573
+ if (typeof setTimeout === 'function') {
574
+ this._initialLoadTimer = setTimeout(triggerLoad, 120);
575
+ return;
576
+ }
577
+ triggerLoad();
578
+ };
579
+ if (document.readyState === 'complete') {
580
+ runInitialLoad();
581
+ } else {
582
+ this._initialLoadOnWindowLoad = () => {
583
+ if (typeof window !== 'undefined' && typeof window.removeEventListener === 'function') {
584
+ window.removeEventListener('load', this._initialLoadOnWindowLoad);
585
+ }
586
+ this._initialLoadOnWindowLoad = null;
587
+ runInitialLoad();
588
+ };
589
+ window.addEventListener('load', this._initialLoadOnWindowLoad, { once: true });
590
+ }
591
+ },
592
+
593
+ beforeUnmount() {
594
+ this.teardownSessionTabRender();
595
+ this.cancelScheduledSessionTabDeferredTeardown();
596
+ this.disconnectSessionPreviewHeaderResizeObserver();
597
+ if (this._initialLoadOnWindowLoad) {
598
+ window.removeEventListener('load', this._initialLoadOnWindowLoad);
599
+ this._initialLoadOnWindowLoad = null;
600
+ }
601
+ if (this._initialLoadRafId) {
602
+ cancelAnimationFrame(this._initialLoadRafId);
603
+ this._initialLoadRafId = 0;
604
+ }
605
+ if (this._initialLoadTimer) {
606
+ clearTimeout(this._initialLoadTimer);
607
+ this._initialLoadTimer = 0;
608
+ }
609
+ window.removeEventListener('resize', this.onWindowResize);
610
+ window.removeEventListener('keydown', this.handleGlobalKeydown);
611
+ window.removeEventListener('beforeunload', this.handleBeforeUnload);
612
+ this.applyCompactLayoutClass(false);
613
+ this.stopTaskOrchestrationPolling();
614
+ this.sessionPreviewScrollEl = null;
615
+ this.sessionPreviewContainerEl = null;
616
+ this.sessionPreviewHeaderEl = null;
617
+ this.clearSessionTimelineRefs();
618
+ },
619
+
620
+ computed: createAppComputed(),
621
+ methods: createAppMethods()
622
+ });
623
+
624
+ app.mount('#app');
625
+ });