codexmate 0.0.20 → 0.0.22

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 (96) hide show
  1. package/README.md +289 -152
  2. package/README.zh.md +321 -0
  3. package/cli/agents-files.js +224 -0
  4. package/cli/archive-helpers.js +446 -0
  5. package/cli/auth-profiles.js +359 -0
  6. package/cli/builtin-proxy.js +1044 -0
  7. package/cli/claude-proxy.js +998 -0
  8. package/cli/config-bootstrap.js +384 -0
  9. package/cli/openai-bridge.js +950 -0
  10. package/cli/openclaw-config.js +629 -0
  11. package/cli/session-usage.concurrent.js +28 -0
  12. package/cli/session-usage.js +112 -0
  13. package/cli/session-usage.models.js +176 -0
  14. package/cli/skills.js +1141 -0
  15. package/cli/zip-commands.js +510 -0
  16. package/cli.js +9408 -9719
  17. package/lib/cli-models-utils.js +109 -1
  18. package/lib/cli-path-utils.js +69 -0
  19. package/lib/cli-sessions.js +386 -0
  20. package/lib/download-artifacts.js +77 -0
  21. package/lib/task-orchestrator.js +869 -0
  22. package/package.json +14 -10
  23. package/res/logo.png +0 -0
  24. package/res/vue.global.prod.js +13 -0
  25. package/web-ui/app.js +193 -15
  26. package/web-ui/index.html +5 -1
  27. package/web-ui/logic.agents-diff.mjs +1 -1
  28. package/web-ui/logic.claude.mjs +60 -0
  29. package/web-ui/logic.runtime.mjs +11 -7
  30. package/web-ui/logic.sessions.mjs +372 -21
  31. package/web-ui/modules/api.mjs +22 -1
  32. package/web-ui/modules/app.computed.dashboard.mjs +23 -10
  33. package/web-ui/modules/app.computed.index.mjs +4 -0
  34. package/web-ui/modules/app.computed.main-tabs.mjs +198 -0
  35. package/web-ui/modules/app.computed.session.mjs +521 -9
  36. package/web-ui/modules/app.methods.agents.mjs +62 -11
  37. package/web-ui/modules/app.methods.codex-config.mjs +189 -34
  38. package/web-ui/modules/app.methods.index.mjs +7 -1
  39. package/web-ui/modules/app.methods.install.mjs +24 -20
  40. package/web-ui/modules/app.methods.navigation.mjs +142 -1
  41. package/web-ui/modules/app.methods.openclaw-core.mjs +339 -39
  42. package/web-ui/modules/app.methods.openclaw-editing.mjs +39 -4
  43. package/web-ui/modules/app.methods.openclaw-persist.mjs +122 -4
  44. package/web-ui/modules/app.methods.providers.mjs +192 -53
  45. package/web-ui/modules/app.methods.session-actions.mjs +99 -19
  46. package/web-ui/modules/app.methods.session-browser.mjs +196 -5
  47. package/web-ui/modules/app.methods.session-timeline.mjs +22 -15
  48. package/web-ui/modules/app.methods.session-trash.mjs +3 -0
  49. package/web-ui/modules/app.methods.startup-claude.mjs +70 -71
  50. package/web-ui/modules/app.methods.task-orchestration.mjs +471 -0
  51. package/web-ui/modules/config-mode.computed.mjs +2 -0
  52. package/web-ui/modules/config-template-confirm-pref.mjs +33 -0
  53. package/web-ui/modules/i18n.mjs +1609 -0
  54. package/web-ui/modules/plugins.computed.mjs +220 -0
  55. package/web-ui/modules/plugins.methods.mjs +620 -0
  56. package/web-ui/modules/plugins.storage.mjs +37 -0
  57. package/web-ui/partials/index/layout-footer.html +1 -57
  58. package/web-ui/partials/index/layout-header.html +299 -175
  59. package/web-ui/partials/index/modal-config-template-agents.html +79 -29
  60. package/web-ui/partials/index/modal-confirm-toast.html +1 -1
  61. package/web-ui/partials/index/modal-health-check.html +14 -14
  62. package/web-ui/partials/index/modal-openclaw-config.html +47 -42
  63. package/web-ui/partials/index/modal-skills.html +130 -114
  64. package/web-ui/partials/index/modals-basic.html +71 -102
  65. package/web-ui/partials/index/panel-config-claude.html +50 -12
  66. package/web-ui/partials/index/panel-config-codex.html +34 -37
  67. package/web-ui/partials/index/panel-config-openclaw.html +10 -16
  68. package/web-ui/partials/index/panel-docs.html +147 -0
  69. package/web-ui/partials/index/panel-market.html +38 -38
  70. package/web-ui/partials/index/panel-orchestration.html +397 -0
  71. package/web-ui/partials/index/panel-plugins.html +243 -0
  72. package/web-ui/partials/index/panel-sessions.html +51 -146
  73. package/web-ui/partials/index/panel-settings.html +188 -96
  74. package/web-ui/partials/index/panel-usage.html +353 -0
  75. package/web-ui/session-helpers.mjs +221 -10
  76. package/web-ui/styles/base-theme.css +120 -229
  77. package/web-ui/styles/controls-forms.css +59 -51
  78. package/web-ui/styles/docs-panel.css +247 -0
  79. package/web-ui/styles/layout-shell.css +394 -128
  80. package/web-ui/styles/modals-core.css +18 -3
  81. package/web-ui/styles/navigation-panels.css +184 -183
  82. package/web-ui/styles/plugins-panel.css +518 -0
  83. package/web-ui/styles/responsive.css +102 -62
  84. package/web-ui/styles/sessions-list.css +13 -27
  85. package/web-ui/styles/sessions-preview.css +13 -7
  86. package/web-ui/styles/sessions-toolbar-trash.css +25 -0
  87. package/web-ui/styles/sessions-usage.css +581 -6
  88. package/web-ui/styles/settings-panel.css +166 -0
  89. package/web-ui/styles/skills-list.css +16 -11
  90. package/web-ui/styles/skills-market.css +63 -2
  91. package/web-ui/styles/task-orchestration.css +776 -0
  92. package/web-ui/styles/titles-cards.css +67 -66
  93. package/web-ui/styles.css +4 -0
  94. package/README.en.md +0 -259
  95. package/res/screenshot.png +0 -0
  96. package/res/vue.global.js +0 -18552
@@ -5,7 +5,7 @@
5
5
  id="panel-settings"
6
6
  role="tabpanel"
7
7
  :aria-labelledby="'tab-settings'">
8
- <div class="config-subtabs settings-subtabs" role="tablist" aria-label="设置子标签">
8
+ <div class="config-subtabs settings-subtabs" role="tablist" aria-label="Settings tabs">
9
9
  <button
10
10
  id="settings-tab-backup"
11
11
  role="tab"
@@ -14,7 +14,7 @@
14
14
  :tabindex="settingsTab === 'backup' ? 0 : -1"
15
15
  :class="['config-subtab', { active: settingsTab === 'backup' }]"
16
16
  @click="onSettingsTabClick('backup')">
17
- 备份与导入
17
+ {{ t('settings.tab.backup') }}
18
18
  </button>
19
19
  <button
20
20
  id="settings-tab-trash"
@@ -24,7 +24,7 @@
24
24
  :tabindex="settingsTab === 'trash' ? 0 : -1"
25
25
  :class="['config-subtab', { active: settingsTab === 'trash' }]"
26
26
  @click="onSettingsTabClick('trash')">
27
- 回收站
27
+ {{ t('settings.tab.trash') }}
28
28
  <span class="settings-tab-badge">{{ sessionTrashCount }}</span>
29
29
  </button>
30
30
  <button
@@ -35,7 +35,7 @@
35
35
  :tabindex="settingsTab === 'device' ? 0 : -1"
36
36
  :class="['config-subtab', { active: settingsTab === 'device' }]"
37
37
  @click="onSettingsTabClick('device')">
38
- 设备
38
+ {{ t('settings.tab.device') }}
39
39
  </button>
40
40
  </div>
41
41
 
@@ -44,39 +44,77 @@
44
44
  id="settings-panel-backup"
45
45
  role="tabpanel"
46
46
  aria-labelledby="settings-tab-backup">
47
- <div class="selector-section">
48
- <div class="selector-header">
49
- <span class="selector-title">Claude 配置</span>
50
- </div>
51
- <button class="btn-tool" @click="downloadClaudeDirectory" :disabled="claudeDownloadLoading">
52
- {{ claudeDownloadLoading ? ('备份中 ' + claudeDownloadProgress + '%') : '一键备份 ~/.claude' }}
53
- </button>
54
- <button class="btn-tool" @click="triggerClaudeImport" :disabled="claudeImportLoading">
55
- {{ claudeImportLoading ? '导入中...' : '导入 ~/.claude 备份' }}
56
- </button>
57
- <input
58
- ref="claudeImportInput"
59
- class="sr-only"
60
- type="file"
61
- accept=".zip"
62
- @change="handleClaudeImportChange">
63
- </div>
64
- <div class="selector-section">
65
- <div class="selector-header">
66
- <span class="selector-title">Codex 配置</span>
47
+ <div class="settings-layout">
48
+ <div class="settings-grid">
49
+ <section class="settings-card settings-card--wide" :aria-label="t('settings.sharePrefix.title')">
50
+ <div class="settings-card-header">
51
+ <div class="settings-card-title">{{ t('settings.sharePrefix.title') }}</div>
52
+ <div class="settings-card-meta">{{ t('settings.sharePrefix.meta') }}</div>
53
+ </div>
54
+ <div class="settings-card-body">
55
+ <div class="settings-field-row">
56
+ <label class="settings-field-label" for="settings-share-prefix">{{ t('settings.sharePrefix.label') }}</label>
57
+ <select
58
+ id="settings-share-prefix"
59
+ class="model-select"
60
+ :value="shareCommandPrefix"
61
+ @change="setShareCommandPrefix($event.target.value)">
62
+ <option value="npm start">npm start</option>
63
+ <option value="codexmate">codexmate</option>
64
+ </select>
65
+ </div>
66
+ <div class="settings-card-hint">
67
+ {{ t('settings.sharePrefix.hint') }}
68
+ </div>
69
+ </div>
70
+ </section>
71
+
72
+ <section class="settings-card" :aria-label="t('settings.claude.title')">
73
+ <div class="settings-card-header">
74
+ <div class="settings-card-title">{{ t('settings.claude.title') }}</div>
75
+ <div class="settings-card-meta">{{ t('settings.claude.meta') }}</div>
76
+ </div>
77
+ <div class="settings-card-body">
78
+ <div class="settings-actions">
79
+ <button class="btn-tool" @click="downloadClaudeDirectory" :disabled="claudeDownloadLoading">
80
+ {{ claudeDownloadLoading ? t('settings.backup.progress', { percent: claudeDownloadProgress }) : t('settings.backup.oneClickClaude') }}
81
+ </button>
82
+ <button class="btn-tool" @click="triggerClaudeImport" :disabled="claudeImportLoading">
83
+ {{ claudeImportLoading ? t('settings.importing') : t('settings.backup.importClaude') }}
84
+ </button>
85
+ </div>
86
+ <input
87
+ ref="claudeImportInput"
88
+ class="sr-only"
89
+ type="file"
90
+ accept=".zip"
91
+ @change="handleClaudeImportChange">
92
+ </div>
93
+ </section>
94
+
95
+ <section class="settings-card" :aria-label="t('settings.codex.title')">
96
+ <div class="settings-card-header">
97
+ <div class="settings-card-title">{{ t('settings.codex.title') }}</div>
98
+ <div class="settings-card-meta">{{ t('settings.codex.meta') }}</div>
99
+ </div>
100
+ <div class="settings-card-body">
101
+ <div class="settings-actions">
102
+ <button class="btn-tool" @click="downloadCodexDirectory" :disabled="codexDownloadLoading">
103
+ {{ codexDownloadLoading ? t('settings.backup.progress', { percent: codexDownloadProgress }) : t('settings.backup.oneClickCodex') }}
104
+ </button>
105
+ <button class="btn-tool" @click="triggerCodexImport" :disabled="codexImportLoading">
106
+ {{ codexImportLoading ? t('settings.importing') : t('settings.backup.importCodex') }}
107
+ </button>
108
+ </div>
109
+ <input
110
+ ref="codexImportInput"
111
+ class="sr-only"
112
+ type="file"
113
+ accept=".zip"
114
+ @change="handleCodexImportChange">
115
+ </div>
116
+ </section>
67
117
  </div>
68
- <button class="btn-tool" @click="downloadCodexDirectory" :disabled="codexDownloadLoading">
69
- {{ codexDownloadLoading ? ('备份中 ' + codexDownloadProgress + '%') : '一键备份 ~/.codex' }}
70
- </button>
71
- <button class="btn-tool" @click="triggerCodexImport" :disabled="codexImportLoading">
72
- {{ codexImportLoading ? '导入中...' : '导入 ~/.codex 备份' }}
73
- </button>
74
- <input
75
- ref="codexImportInput"
76
- class="sr-only"
77
- type="file"
78
- accept=".zip"
79
- @change="handleCodexImportChange">
80
118
  </div>
81
119
  </div>
82
120
 
@@ -85,65 +123,91 @@
85
123
  id="settings-panel-trash"
86
124
  role="tabpanel"
87
125
  aria-labelledby="settings-tab-trash">
88
- <div class="selector-section">
89
- <div class="selector-header settings-tab-header">
90
- <div class="settings-tab-actions trash-header-actions">
91
- <button class="btn-tool btn-tool-compact" @click="loadSessionTrash({ forceRefresh: true })" :disabled="sessionTrashLoading || sessionTrashClearing">
92
- {{ sessionTrashLoading ? '刷新中...' : '刷新列表' }}
93
- </button>
94
- <button class="btn-tool btn-tool-compact" @click="clearSessionTrash" :disabled="sessionTrashClearing || sessionTrashLoading || !(Number(sessionTrashCount) > 0)">
95
- {{ sessionTrashClearing ? '清空中...' : '清空回收站' }}
96
- </button>
97
- </div>
98
- </div>
126
+ <div class="settings-layout">
127
+ <div class="settings-grid">
128
+ <section class="settings-card settings-card--wide" :aria-label="t('settings.deleteBehavior.title')">
129
+ <div class="settings-card-header">
130
+ <div class="settings-card-title">{{ t('settings.deleteBehavior.title') }}</div>
131
+ <div class="settings-card-meta">{{ t('settings.deleteBehavior.meta') }}</div>
132
+ </div>
133
+ <div class="settings-card-body">
134
+ <label class="health-remote-toggle settings-toggle">
135
+ <input type="checkbox" :checked="sessionTrashEnabled" @change="setSessionTrashEnabled($event.target.checked)">
136
+ <span>{{ t('settings.deleteBehavior.toggle') }}</span>
137
+ </label>
138
+ <div class="settings-card-hint">
139
+ {{ t('settings.deleteBehavior.hint') }}
140
+ </div>
141
+ </div>
142
+ </section>
99
143
 
100
- <div v-if="getSessionTrashViewState() === 'loading'" class="session-empty">
101
- 正在加载回收站...
102
- </div>
103
- <div v-else-if="getSessionTrashViewState() === 'empty'" class="session-empty">
104
- 回收站为空
105
- </div>
106
- <div v-else-if="getSessionTrashViewState() === 'retry'" class="session-empty">
107
- 回收站列表加载失败,请刷新重试
108
- </div>
109
- <div v-else class="trash-list">
110
- <div v-for="item in visibleSessionTrashItems" :key="item.trashId" class="trash-item session-item session-card">
111
- <div class="trash-item-header session-item-header">
112
- <div class="trash-item-main">
113
- <div class="trash-item-mainline">
114
- <div class="trash-item-title">{{ item.title || item.sessionId }}</div>
115
- <span class="session-count-badge">{{ item.messageCount ?? 0 }}</span>
116
- </div>
117
- <div class="trash-item-meta session-item-meta">
118
- <span class="session-source">{{ item.sourceLabel }}</span>
119
- </div>
144
+ <section class="settings-card settings-card--wide" :aria-label="t('settings.trash.title')">
145
+ <div class="settings-card-header settings-card-header-row">
146
+ <div>
147
+ <div class="settings-card-title">{{ t('settings.trash.title') }}</div>
148
+ <div class="settings-card-meta">{{ t('settings.trash.meta') }}</div>
120
149
  </div>
121
- <div class="trash-item-side">
122
- <div class="trash-item-actions session-item-actions">
123
- <button class="btn-mini" @click="restoreSessionTrash(item)" :disabled="sessionTrashLoading || sessionTrashClearing || isSessionTrashActionBusy(item)">
124
- {{ sessionTrashRestoring[getSessionTrashActionKey(item)] ? '恢复中...' : '恢复' }}
125
- </button>
126
- <button class="btn-mini delete" @click="purgeSessionTrash(item)" :disabled="sessionTrashLoading || sessionTrashClearing || isSessionTrashActionBusy(item)">
127
- {{ sessionTrashPurging[getSessionTrashActionKey(item)] ? '删除中...' : '彻底删除' }}
150
+ <div class="settings-card-actions">
151
+ <button class="btn-tool btn-tool-compact" @click="loadSessionTrash({ forceRefresh: true })" :disabled="sessionTrashLoading || sessionTrashClearing">
152
+ {{ sessionTrashLoading ? t('settings.trash.refreshing') : t('settings.trash.refresh') }}
153
+ </button>
154
+ <button class="btn-tool btn-tool-compact" @click="clearSessionTrash" :disabled="sessionTrashClearing || sessionTrashLoading || !(Number(sessionTrashCount) > 0)">
155
+ {{ sessionTrashClearing ? t('settings.trash.clearing') : t('settings.trash.clear') }}
156
+ </button>
157
+ </div>
158
+ </div>
159
+
160
+ <div class="settings-card-body">
161
+ <div v-if="getSessionTrashViewState() === 'loading'" class="session-empty">
162
+ {{ t('settings.trash.loading') }}
163
+ </div>
164
+ <div v-else-if="getSessionTrashViewState() === 'empty'" class="session-empty">
165
+ {{ t('settings.trash.empty') }}
166
+ </div>
167
+ <div v-else-if="getSessionTrashViewState() === 'retry'" class="session-empty">
168
+ {{ t('settings.trash.retry') }}
169
+ </div>
170
+ <div v-else class="trash-list">
171
+ <div v-for="item in visibleSessionTrashItems" :key="item.trashId" class="trash-item session-item session-card">
172
+ <div class="trash-item-header session-item-header">
173
+ <div class="trash-item-main">
174
+ <div class="trash-item-mainline">
175
+ <div class="trash-item-title">{{ item.title || item.sessionId }}</div>
176
+ <span class="session-count-badge">{{ item.messageCount == null ? 0 : item.messageCount }}</span>
177
+ </div>
178
+ <div class="trash-item-meta session-item-meta">
179
+ <span class="session-source">{{ item.sourceLabel }}</span>
180
+ </div>
181
+ </div>
182
+ <div class="trash-item-side">
183
+ <div class="trash-item-actions session-item-actions">
184
+ <button class="btn-mini" @click="restoreSessionTrash(item)" :disabled="sessionTrashLoading || sessionTrashClearing || isSessionTrashActionBusy(item)">
185
+ {{ sessionTrashRestoring[getSessionTrashActionKey(item)] ? t('settings.trash.restoring') : t('settings.trash.restore') }}
186
+ </button>
187
+ <button class="btn-mini delete" @click="purgeSessionTrash(item)" :disabled="sessionTrashLoading || sessionTrashClearing || isSessionTrashActionBusy(item)">
188
+ {{ sessionTrashPurging[getSessionTrashActionKey(item)] ? t('settings.trash.purging') : t('settings.trash.purge') }}
189
+ </button>
190
+ </div>
191
+ <div class="trash-item-time session-item-time">{{ item.deletedAt || item.updatedAt || t('sessions.unknownTime') }}</div>
192
+ </div>
193
+ </div>
194
+ <div v-if="item.cwd" class="trash-item-path session-item-sub session-item-wrap">
195
+ <span class="trash-item-label">{{ t('settings.trash.workspace') }}</span>
196
+ <span>{{ item.cwd }}</span>
197
+ </div>
198
+ <div class="trash-item-path session-item-sub session-item-wrap">
199
+ <span class="trash-item-label">{{ t('settings.trash.originalFile') }}</span>
200
+ <span>{{ item.originalFilePath }}</span>
201
+ </div>
202
+ </div>
203
+ <div v-if="sessionTrashHasMoreItems" class="trash-list-footer">
204
+ <button class="btn-tool btn-tool-compact" @click="loadMoreSessionTrashItems" :disabled="sessionTrashLoading || sessionTrashClearing">
205
+ {{ t('settings.trash.loadMore', { count: sessionTrashHiddenCount }) }}
128
206
  </button>
129
207
  </div>
130
- <div class="trash-item-time session-item-time">{{ item.deletedAt || item.updatedAt || 'unknown time' }}</div>
131
208
  </div>
132
209
  </div>
133
- <div v-if="item.cwd" class="trash-item-path session-item-sub session-item-wrap">
134
- <span class="trash-item-label">工作区</span>
135
- <span>{{ item.cwd }}</span>
136
- </div>
137
- <div class="trash-item-path session-item-sub session-item-wrap">
138
- <span class="trash-item-label">原文件</span>
139
- <span>{{ item.originalFilePath }}</span>
140
- </div>
141
- </div>
142
- <div v-if="sessionTrashHasMoreItems" class="trash-list-footer">
143
- <button class="btn-tool btn-tool-compact" @click="loadMoreSessionTrashItems" :disabled="sessionTrashLoading || sessionTrashClearing">
144
- 加载更多(剩余 {{ sessionTrashHiddenCount }} 项)
145
- </button>
146
- </div>
210
+ </section>
147
211
  </div>
148
212
  </div>
149
213
  </div>
@@ -153,14 +217,42 @@
153
217
  id="settings-panel-device"
154
218
  role="tabpanel"
155
219
  aria-labelledby="settings-tab-device">
156
- <div class="selector-section">
157
- <div class="selector-header">
158
- <span class="selector-title">配置重置</span>
220
+ <div class="settings-layout">
221
+ <div class="settings-grid">
222
+ <section class="settings-card settings-card--wide" :aria-label="t('settings.templateConfirm.title')">
223
+ <div class="settings-card-header">
224
+ <div class="settings-card-title">{{ t('settings.templateConfirm.title') }}</div>
225
+ <div class="settings-card-meta">{{ t('settings.templateConfirm.meta') }}</div>
226
+ </div>
227
+ <div class="settings-card-body">
228
+ <label class="health-remote-toggle settings-toggle">
229
+ <input
230
+ type="checkbox"
231
+ :checked="configTemplateDiffConfirmEnabled"
232
+ @change="setConfigTemplateDiffConfirmEnabled($event.target.checked)">
233
+ <span>{{ t('settings.templateConfirm.toggle') }}</span>
234
+ </label>
235
+ <div class="settings-card-hint">
236
+ {{ t('settings.templateConfirm.hint') }}
237
+ </div>
238
+ </div>
239
+ </section>
240
+
241
+ <section class="settings-card settings-card--wide settings-card--danger" :aria-label="t('settings.reset.title')">
242
+ <div class="settings-card-header">
243
+ <div class="settings-card-title">{{ t('settings.reset.title') }}</div>
244
+ <div class="settings-card-meta">{{ t('settings.reset.meta') }}</div>
245
+ </div>
246
+ <div class="settings-card-body">
247
+ <div class="settings-card-hint">{{ t('settings.reset.hint') }}</div>
248
+ <div class="settings-actions">
249
+ <button class="btn-tool" @click="resetConfig" :disabled="resetConfigLoading || loading || !!initError">
250
+ {{ resetConfigLoading ? t('settings.reset.loading') : t('settings.reset.button') }}
251
+ </button>
252
+ </div>
253
+ </div>
254
+ </section>
159
255
  </div>
160
- <div class="config-template-hint">先备份 config.toml,再写默认配置。</div>
161
- <button class="btn-tool" @click="resetConfig" :disabled="resetConfigLoading || loading || !!initError">
162
- {{ resetConfigLoading ? '重装中...' : '重装配置' }}
163
- </button>
164
256
  </div>
165
257
  </div>
166
258
  </div>