codexmate 0.0.32 → 0.0.34

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