codexmate 0.0.29 → 0.0.31

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