codexmate 0.0.54 → 0.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/README.vi.md +170 -0
- package/cli.js +553 -5
- package/package.json +1 -1
- package/web-ui/app.js +38 -0
- package/web-ui/logic.claude.mjs +8 -0
- package/web-ui/modules/app.methods.claude-config.mjs +72 -5
- package/web-ui/modules/app.methods.index.mjs +4 -0
- package/web-ui/modules/app.methods.navigation.mjs +3 -0
- package/web-ui/modules/app.methods.provider-cache.mjs +223 -0
- package/web-ui/modules/app.methods.session-actions.mjs +12 -0
- package/web-ui/modules/app.methods.session-browser.mjs +3 -0
- package/web-ui/modules/app.methods.session-trash.mjs +3 -0
- package/web-ui/modules/app.methods.startup-claude.mjs +13 -3
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +161 -0
- package/web-ui/modules/i18n/locales/en.mjs +65 -1
- package/web-ui/modules/i18n/locales/ja.mjs +62 -1
- package/web-ui/modules/i18n/locales/vi.mjs +917 -0
- package/web-ui/modules/i18n/locales/zh-tw.mjs +62 -1
- package/web-ui/modules/i18n/locales/zh.mjs +62 -1
- package/web-ui/partials/index/layout-header.html +18 -5
- package/web-ui/partials/index/modals-basic.html +182 -0
- package/web-ui/partials/index/panel-sessions.html +2 -2
- package/web-ui/partials/index/panel-settings.html +20 -0
- package/web-ui/res/web-ui-render.precompiled.js +397 -20
- package/web-ui/styles/layout-shell.css +51 -1
- package/web-ui/styles/settings-panel.css +398 -0
|
@@ -1088,6 +1088,39 @@ const zhTw = Object.freeze({
|
|
|
1088
1088
|
'settings.tabs.aria': '設定分類',
|
|
1089
1089
|
'settings.quickSettings.title': '快捷設定',
|
|
1090
1090
|
'settings.language.sideLabel': '語言:{language}',
|
|
1091
|
+
'announcement.providerCache.open': '功能公告',
|
|
1092
|
+
'announcement.project.eyebrow': '新手入口',
|
|
1093
|
+
'announcement.project.closeAria': '關閉功能公告',
|
|
1094
|
+
'announcement.project.primaryAction': '進入工作台',
|
|
1095
|
+
'announcement.project.title': '你的 AI 工具入口在這裡',
|
|
1096
|
+
'announcement.project.subtitle': '從這裡連接模型、找回對話、查看用量,並把常用維護動作放到一個工作台裡。',
|
|
1097
|
+
'announcement.project.features.aria': 'Codex Mate 功能概覽',
|
|
1098
|
+
'announcement.project.feature.config.title': '連接模型',
|
|
1099
|
+
'announcement.project.feature.config.meta': '配置常用 AI 工具的模型和服務地址。',
|
|
1100
|
+
'announcement.project.feature.sessions.title': '找回對話',
|
|
1101
|
+
'announcement.project.feature.sessions.meta': '按來源搜尋、匯出或清理歷史會話。',
|
|
1102
|
+
'announcement.project.feature.usage.title': '查看花費',
|
|
1103
|
+
'announcement.project.feature.usage.meta': '看最近和長期的本地用量趨勢。',
|
|
1104
|
+
'announcement.project.feature.tasks.title': '追蹤任務',
|
|
1105
|
+
'announcement.project.feature.tasks.meta': '查看計畫、佇列和執行記錄。',
|
|
1106
|
+
'announcement.project.feature.skills.title': '複用工作流',
|
|
1107
|
+
'announcement.project.feature.skills.meta': '管理 Skills 和提示詞範本。',
|
|
1108
|
+
'announcement.project.feature.data.title': '整理資料',
|
|
1109
|
+
'announcement.project.feature.data.meta': '處理備份、匯入、回收站和快取。',
|
|
1110
|
+
'announcement.project.status.aria': '目前工作台狀態',
|
|
1111
|
+
'announcement.project.status.provider': 'Provider',
|
|
1112
|
+
'announcement.project.status.model': '目前模型',
|
|
1113
|
+
'announcement.project.status.cacheFiles': '快取檔案',
|
|
1114
|
+
'announcement.project.cache.title': '進階維護狀態',
|
|
1115
|
+
'announcement.project.cache.meta': '僅在需要排查或同步時展開;日常使用可以忽略。',
|
|
1116
|
+
'announcement.project.cache.files': '快取檔案',
|
|
1117
|
+
'announcement.project.cache.providers': 'Provider 摘要',
|
|
1118
|
+
'announcement.project.cache.groups': '快取分組',
|
|
1119
|
+
'announcement.project.cache.groupList': 'Provider 快取分組摘要',
|
|
1120
|
+
'announcement.project.cache.groupSummary': '{files} 檔案 · {providers} provider',
|
|
1121
|
+
'announcement.project.cache.sync': '同步快取',
|
|
1122
|
+
'announcement.project.cache.refresh': '重新整理摘要',
|
|
1123
|
+
'announcement.project.cache.details': '查看快取詳情',
|
|
1091
1124
|
'settings.language.title': '語言',
|
|
1092
1125
|
'settings.language.meta': '選擇 Web UI 的顯示語言',
|
|
1093
1126
|
'settings.language.label': '界面語言',
|
|
@@ -1095,7 +1128,7 @@ const zhTw = Object.freeze({
|
|
|
1095
1128
|
'settings.sharePrefix.title': '分享命令前綴',
|
|
1096
1129
|
'settings.sharePrefix.meta': '影響 Web UI 裡“複製分享命令”的前綴',
|
|
1097
1130
|
'settings.sharePrefix.label': '前綴',
|
|
1098
|
-
'settings.sharePrefix.hint': '預設走項目內 npm start,也可切到全局 codexmate
|
|
1131
|
+
'settings.sharePrefix.hint': '預設走項目內 npm start,也可切到全局 codexmate。該設定會寫入 ~/.codexmate/preferences.json。',
|
|
1099
1132
|
'settings.backup.title': '資料備份',
|
|
1100
1133
|
'settings.backup.meta': '匯出 / 匯入 Claude 與 Codex 設定',
|
|
1101
1134
|
'settings.claude.title': 'Claude 設定',
|
|
@@ -1109,6 +1142,34 @@ const zhTw = Object.freeze({
|
|
|
1109
1142
|
'settings.backup.importCodex': '匯入 ~/.codex 備份',
|
|
1110
1143
|
'settings.importing': '匯入中...',
|
|
1111
1144
|
|
|
1145
|
+
'settings.providerCache.title': 'Provider 快取記錄',
|
|
1146
|
+
'settings.providerCache.meta': '查看 ~/.codexmate 內的 Claude / Codex / OpenCode 快取',
|
|
1147
|
+
'settings.providerCache.open': '查看快取記錄',
|
|
1148
|
+
'settings.providerCache.sync': '同步快取記錄',
|
|
1149
|
+
'settings.providerCache.syncing': '同步中...',
|
|
1150
|
+
'settings.providerCache.loading': '載入中...',
|
|
1151
|
+
'settings.providerCache.hint': '只讀展示快取文件,敏感欄位會自動遮罩。同步會把目前 provider 設定寫入 ~/.codexmate 快取文件。',
|
|
1152
|
+
'modal.providerCache.title': 'Provider 快取記錄',
|
|
1153
|
+
'modal.providerCache.root': '快取目錄',
|
|
1154
|
+
'modal.providerCache.refresh': '重新整理',
|
|
1155
|
+
'modal.providerCache.refreshing': '重新整理中...',
|
|
1156
|
+
'modal.providerCache.sync': '同步',
|
|
1157
|
+
'modal.providerCache.syncing': '同步中...',
|
|
1158
|
+
'modal.providerCache.syncSucceeded': '已同步 {count} 個 provider 到 {fileCount} 個快取文件',
|
|
1159
|
+
'modal.providerCache.syncFailed': '同步快取記錄失敗',
|
|
1160
|
+
'modal.providerCache.noSyncableProviders': '沒有可同步的 provider',
|
|
1161
|
+
'modal.providerCache.loading': '正在載入快取記錄...',
|
|
1162
|
+
'modal.providerCache.loadedAt': '載入時間',
|
|
1163
|
+
'modal.providerCache.groupMeta': '已發現 {count} 個快取文件',
|
|
1164
|
+
'modal.providerCache.empty': '沒有發現快取文件',
|
|
1165
|
+
'modal.providerCache.providerCount': '{count} 個 provider',
|
|
1166
|
+
'modal.providerCache.rawJsonOnly': '未識別到 provider 摘要,顯示原始 JSON',
|
|
1167
|
+
'modal.providerCache.tooLarge': '文件過大,已跳過 JSON 讀取',
|
|
1168
|
+
'modal.providerCache.parseFailed': 'JSON 解析失敗',
|
|
1169
|
+
'modal.providerCache.rawJson': '原始 JSON',
|
|
1170
|
+
'modal.providerCache.errorDetails': '錯誤詳情',
|
|
1171
|
+
'modal.providerCache.loadFailed': '載入快取記錄失敗',
|
|
1172
|
+
|
|
1112
1173
|
'settings.trashConfig.title': '回收站設定',
|
|
1113
1174
|
'settings.trashConfig.meta': '回收站開關與自動清理天數',
|
|
1114
1175
|
'settings.deleteBehavior.title': '會話刪除行為',
|
|
@@ -1088,6 +1088,39 @@ const zh = Object.freeze({
|
|
|
1088
1088
|
'settings.tabs.aria': '设置分类',
|
|
1089
1089
|
'settings.quickSettings.title': '快捷设置',
|
|
1090
1090
|
'settings.language.sideLabel': '语言:{language}',
|
|
1091
|
+
'announcement.providerCache.open': '功能公告',
|
|
1092
|
+
'announcement.project.eyebrow': '新手入口',
|
|
1093
|
+
'announcement.project.closeAria': '关闭功能公告',
|
|
1094
|
+
'announcement.project.primaryAction': '进入工作台',
|
|
1095
|
+
'announcement.project.title': '你的 AI 工具入口在这里',
|
|
1096
|
+
'announcement.project.subtitle': '从这里连接模型、找回对话、查看用量,并把常用维护动作放到一个工作台里。',
|
|
1097
|
+
'announcement.project.features.aria': 'Codex Mate 功能概览',
|
|
1098
|
+
'announcement.project.feature.config.title': '连接模型',
|
|
1099
|
+
'announcement.project.feature.config.meta': '配置常用 AI 工具的模型和服务地址。',
|
|
1100
|
+
'announcement.project.feature.sessions.title': '找回对话',
|
|
1101
|
+
'announcement.project.feature.sessions.meta': '按来源搜索、导出或清理历史会话。',
|
|
1102
|
+
'announcement.project.feature.usage.title': '查看花费',
|
|
1103
|
+
'announcement.project.feature.usage.meta': '看最近和长期的本地用量趋势。',
|
|
1104
|
+
'announcement.project.feature.tasks.title': '跟踪任务',
|
|
1105
|
+
'announcement.project.feature.tasks.meta': '查看计划、队列和运行记录。',
|
|
1106
|
+
'announcement.project.feature.skills.title': '复用工作流',
|
|
1107
|
+
'announcement.project.feature.skills.meta': '管理 Skills 和提示词模板。',
|
|
1108
|
+
'announcement.project.feature.data.title': '整理数据',
|
|
1109
|
+
'announcement.project.feature.data.meta': '处理备份、导入、回收站和缓存。',
|
|
1110
|
+
'announcement.project.status.aria': '当前工作台状态',
|
|
1111
|
+
'announcement.project.status.provider': 'Provider',
|
|
1112
|
+
'announcement.project.status.model': '当前模型',
|
|
1113
|
+
'announcement.project.status.cacheFiles': '缓存文件',
|
|
1114
|
+
'announcement.project.cache.title': '高级维护状态',
|
|
1115
|
+
'announcement.project.cache.meta': '仅在需要排查或同步时展开;日常使用可以忽略。',
|
|
1116
|
+
'announcement.project.cache.files': '缓存文件',
|
|
1117
|
+
'announcement.project.cache.providers': 'Provider 摘要',
|
|
1118
|
+
'announcement.project.cache.groups': '缓存分组',
|
|
1119
|
+
'announcement.project.cache.groupList': 'Provider 缓存分组摘要',
|
|
1120
|
+
'announcement.project.cache.groupSummary': '{files} 文件 · {providers} provider',
|
|
1121
|
+
'announcement.project.cache.sync': '同步缓存',
|
|
1122
|
+
'announcement.project.cache.refresh': '刷新摘要',
|
|
1123
|
+
'announcement.project.cache.details': '查看缓存详情',
|
|
1091
1124
|
'settings.language.title': '语言',
|
|
1092
1125
|
'settings.language.meta': '选择 Web UI 的显示语言',
|
|
1093
1126
|
'settings.language.label': '界面语言',
|
|
@@ -1095,7 +1128,7 @@ const zh = Object.freeze({
|
|
|
1095
1128
|
'settings.sharePrefix.title': '分享命令前缀',
|
|
1096
1129
|
'settings.sharePrefix.meta': '影响 Web UI 里“复制分享命令”的前缀',
|
|
1097
1130
|
'settings.sharePrefix.label': '前缀',
|
|
1098
|
-
'settings.sharePrefix.hint': '默认走项目内 npm start,也可切到全局 codexmate
|
|
1131
|
+
'settings.sharePrefix.hint': '默认走项目内 npm start,也可切到全局 codexmate。该设置会写入 ~/.codexmate/preferences.json。',
|
|
1099
1132
|
'settings.backup.title': '数据备份',
|
|
1100
1133
|
'settings.backup.meta': '导出 / 导入 Claude 与 Codex 配置',
|
|
1101
1134
|
'settings.claude.title': 'Claude 配置',
|
|
@@ -1109,6 +1142,34 @@ const zh = Object.freeze({
|
|
|
1109
1142
|
'settings.backup.importCodex': '导入 ~/.codex 备份',
|
|
1110
1143
|
'settings.importing': '导入中...',
|
|
1111
1144
|
|
|
1145
|
+
'settings.providerCache.title': 'Provider 缓存记录',
|
|
1146
|
+
'settings.providerCache.meta': '查看 ~/.codexmate 内的 Claude / Codex / OpenCode 缓存',
|
|
1147
|
+
'settings.providerCache.open': '查看缓存记录',
|
|
1148
|
+
'settings.providerCache.sync': '同步缓存记录',
|
|
1149
|
+
'settings.providerCache.syncing': '同步中...',
|
|
1150
|
+
'settings.providerCache.loading': '加载中...',
|
|
1151
|
+
'settings.providerCache.hint': '只读展示缓存文件,敏感字段会自动遮罩。同步会把当前 provider 配置写入 ~/.codexmate 缓存文件。',
|
|
1152
|
+
'modal.providerCache.title': 'Provider 缓存记录',
|
|
1153
|
+
'modal.providerCache.root': '缓存目录',
|
|
1154
|
+
'modal.providerCache.refresh': '刷新',
|
|
1155
|
+
'modal.providerCache.refreshing': '刷新中...',
|
|
1156
|
+
'modal.providerCache.sync': '同步',
|
|
1157
|
+
'modal.providerCache.syncing': '同步中...',
|
|
1158
|
+
'modal.providerCache.syncSucceeded': '已同步 {count} 个 provider 到 {fileCount} 个缓存文件',
|
|
1159
|
+
'modal.providerCache.syncFailed': '同步缓存记录失败',
|
|
1160
|
+
'modal.providerCache.noSyncableProviders': '没有可同步的 provider',
|
|
1161
|
+
'modal.providerCache.loading': '正在加载缓存记录...',
|
|
1162
|
+
'modal.providerCache.loadedAt': '加载时间',
|
|
1163
|
+
'modal.providerCache.groupMeta': '已发现 {count} 个缓存文件',
|
|
1164
|
+
'modal.providerCache.empty': '没有发现缓存文件',
|
|
1165
|
+
'modal.providerCache.providerCount': '{count} 个 provider',
|
|
1166
|
+
'modal.providerCache.rawJsonOnly': '未识别到 provider 摘要,显示原始 JSON',
|
|
1167
|
+
'modal.providerCache.tooLarge': '文件过大,已跳过 JSON 读取',
|
|
1168
|
+
'modal.providerCache.parseFailed': 'JSON 解析失败',
|
|
1169
|
+
'modal.providerCache.rawJson': '原始 JSON',
|
|
1170
|
+
'modal.providerCache.errorDetails': '错误详情',
|
|
1171
|
+
'modal.providerCache.loadFailed': '加载缓存记录失败',
|
|
1172
|
+
|
|
1112
1173
|
'settings.trashConfig.title': '回收站配置',
|
|
1113
1174
|
'settings.trashConfig.meta': '回收站开关与自动清理天数',
|
|
1114
1175
|
'settings.deleteBehavior.title': '会话删除行为',
|
|
@@ -385,11 +385,24 @@
|
|
|
385
385
|
</div>
|
|
386
386
|
|
|
387
387
|
<div class="side-rail-lang">
|
|
388
|
-
<
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
388
|
+
<div class="side-rail-lang-actions">
|
|
389
|
+
<button
|
|
390
|
+
type="button"
|
|
391
|
+
class="language-settings-link"
|
|
392
|
+
:aria-label="t('settings.language.sideLabel', { language: currentLanguageLabel() })"
|
|
393
|
+
@click="openLanguageSettings">{{ t('settings.language.sideLabel', { language: currentLanguageLabel() }) }}</button>
|
|
394
|
+
<button
|
|
395
|
+
type="button"
|
|
396
|
+
class="side-announcement-button"
|
|
397
|
+
:aria-label="t('announcement.providerCache.open')"
|
|
398
|
+
:title="t('announcement.providerCache.open')"
|
|
399
|
+
@click="openProviderCacheAnnouncementModal">
|
|
400
|
+
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" width="16" height="16" aria-hidden="true">
|
|
401
|
+
<path d="M15 8.5a5 5 0 0 0-10 0c0 2.75-1 4.25-2 5.5h14c-1-1.25-2-2.75-2-5.5Z"/>
|
|
402
|
+
<path d="M8 16a2 2 0 0 0 4 0"/>
|
|
403
|
+
</svg>
|
|
404
|
+
</button>
|
|
405
|
+
</div>
|
|
393
406
|
</div>
|
|
394
407
|
</aside>
|
|
395
408
|
<main class="main-panel">
|
|
@@ -134,6 +134,188 @@
|
|
|
134
134
|
</div>
|
|
135
135
|
</div>
|
|
136
136
|
|
|
137
|
+
<!-- 项目功能公告模态框 -->
|
|
138
|
+
<div v-if="showProviderCacheAnnouncementModal" class="modal-overlay project-announcement-overlay" @click.self="closeProviderCacheAnnouncementModal">
|
|
139
|
+
<div class="modal provider-cache-announcement-modal project-announcement-modal" role="dialog" aria-modal="true" aria-labelledby="provider-cache-announcement-title">
|
|
140
|
+
<button type="button" class="project-announcement-close" :aria-label="t('announcement.project.closeAria')" @click="closeProviderCacheAnnouncementModal">×</button>
|
|
141
|
+
<div class="project-announcement-header">
|
|
142
|
+
<div class="project-announcement-eyebrow">{{ t('announcement.project.eyebrow') }}</div>
|
|
143
|
+
<div class="modal-title project-announcement-title" id="provider-cache-announcement-title">{{ t('announcement.project.title') }}</div>
|
|
144
|
+
<p class="provider-cache-announcement-copy provider-cache-announcement-lede">{{ t('announcement.project.subtitle') }}</p>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="project-announcement-feature-grid" :aria-label="t('announcement.project.features.aria')">
|
|
148
|
+
<article class="project-announcement-feature-card">
|
|
149
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.config.title') }}</div>
|
|
150
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.config.meta') }}</div>
|
|
151
|
+
</article>
|
|
152
|
+
<article class="project-announcement-feature-card">
|
|
153
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.sessions.title') }}</div>
|
|
154
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.sessions.meta') }}</div>
|
|
155
|
+
</article>
|
|
156
|
+
<article class="project-announcement-feature-card">
|
|
157
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.usage.title') }}</div>
|
|
158
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.usage.meta') }}</div>
|
|
159
|
+
</article>
|
|
160
|
+
<article class="project-announcement-feature-card">
|
|
161
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.tasks.title') }}</div>
|
|
162
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.tasks.meta') }}</div>
|
|
163
|
+
</article>
|
|
164
|
+
<article class="project-announcement-feature-card">
|
|
165
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.skills.title') }}</div>
|
|
166
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.skills.meta') }}</div>
|
|
167
|
+
</article>
|
|
168
|
+
<article class="project-announcement-feature-card">
|
|
169
|
+
<div class="project-announcement-feature-title">{{ t('announcement.project.feature.data.title') }}</div>
|
|
170
|
+
<div class="project-announcement-feature-meta">{{ t('announcement.project.feature.data.meta') }}</div>
|
|
171
|
+
</article>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<details class="project-announcement-cache-section" aria-labelledby="project-announcement-cache-title">
|
|
175
|
+
<summary class="project-announcement-section-head">
|
|
176
|
+
<span>
|
|
177
|
+
<span class="project-announcement-section-title" id="project-announcement-cache-title">{{ t('announcement.project.cache.title') }}</span>
|
|
178
|
+
<span class="project-announcement-section-meta">{{ t('announcement.project.cache.meta') }}</span>
|
|
179
|
+
</span>
|
|
180
|
+
<span v-if="getProviderCacheAnnouncementSummary().loadedAt" class="provider-cache-loaded-at">{{ t('modal.providerCache.loadedAt') }}: {{ getProviderCacheAnnouncementSummary().loadedAt }}</span>
|
|
181
|
+
</summary>
|
|
182
|
+
|
|
183
|
+
<div v-if="providerCacheError" class="state-message error provider-cache-error">
|
|
184
|
+
{{ providerCacheError }}
|
|
185
|
+
</div>
|
|
186
|
+
<div v-if="providerCacheSyncMessage" class="state-message provider-cache-sync-message">
|
|
187
|
+
{{ providerCacheSyncMessage }}
|
|
188
|
+
</div>
|
|
189
|
+
<div v-if="providerCacheLoading && !providerCacheLoadedOnce" class="state-message">
|
|
190
|
+
{{ t('modal.providerCache.loading') }}
|
|
191
|
+
</div>
|
|
192
|
+
<div class="provider-cache-announcement-body">
|
|
193
|
+
<div class="project-announcement-mini-status" :aria-label="t('announcement.project.status.aria')">
|
|
194
|
+
<span>{{ t('announcement.project.status.provider') }}: <strong>{{ currentProvider || t('common.notSelected') }}</strong></span>
|
|
195
|
+
<span>{{ t('announcement.project.status.model') }}: <strong>{{ currentModel || t('common.notSelected') }}</strong></span>
|
|
196
|
+
<span>{{ t('announcement.project.status.cacheFiles') }}: <strong>{{ getProviderCacheAnnouncementSummary().fileCount }}</strong></span>
|
|
197
|
+
</div>
|
|
198
|
+
<div class="provider-cache-summary-grid">
|
|
199
|
+
<div class="provider-cache-summary-card">
|
|
200
|
+
<span class="provider-cache-summary-label">{{ t('announcement.project.cache.files') }}</span>
|
|
201
|
+
<strong>{{ getProviderCacheAnnouncementSummary().fileCount }}</strong>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="provider-cache-summary-card">
|
|
204
|
+
<span class="provider-cache-summary-label">{{ t('announcement.project.cache.providers') }}</span>
|
|
205
|
+
<strong>{{ getProviderCacheAnnouncementSummary().providerCount }}</strong>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="provider-cache-summary-card">
|
|
208
|
+
<span class="provider-cache-summary-label">{{ t('announcement.project.cache.groups') }}</span>
|
|
209
|
+
<strong>{{ getProviderCacheAnnouncementSummary().groupCount }}</strong>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="provider-cache-announcement-list" :aria-label="t('announcement.project.cache.groupList')">
|
|
213
|
+
<div v-for="group in getProviderCacheAnnouncementGroups()" :key="group.key" class="provider-cache-announcement-row">
|
|
214
|
+
<span>{{ group.label }}</span>
|
|
215
|
+
<span>{{ t('announcement.project.cache.groupSummary', { files: group.existingCount, providers: group.providerCount }) }}</span>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
<div class="project-announcement-cache-actions">
|
|
219
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="syncProviderCacheRecords" :disabled="providerCacheLoading || providerCacheSyncing">
|
|
220
|
+
{{ providerCacheSyncing ? t('modal.providerCache.syncing') : t('announcement.project.cache.sync') }}
|
|
221
|
+
</button>
|
|
222
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="loadProviderCacheRecords" :disabled="providerCacheLoading">
|
|
223
|
+
{{ providerCacheLoading ? t('modal.providerCache.refreshing') : t('announcement.project.cache.refresh') }}
|
|
224
|
+
</button>
|
|
225
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="openProviderCacheDetailsFromAnnouncement">
|
|
226
|
+
{{ t('announcement.project.cache.details') }}
|
|
227
|
+
</button>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</details>
|
|
231
|
+
|
|
232
|
+
<div class="btn-group provider-cache-footer project-announcement-footer">
|
|
233
|
+
<button class="btn btn-confirm" @click="closeProviderCacheAnnouncementModal">{{ t('announcement.project.primaryAction') }}</button>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<!-- Provider 缓存记录模态框 -->
|
|
239
|
+
<div v-if="showProviderCacheModal" class="modal-overlay" @click.self="closeProviderCacheModal">
|
|
240
|
+
<div class="modal modal-wide provider-cache-modal" role="dialog" aria-modal="true" aria-labelledby="provider-cache-modal-title">
|
|
241
|
+
<div class="modal-title" id="provider-cache-modal-title">{{ t('modal.providerCache.title') }}</div>
|
|
242
|
+
<div class="form-hint provider-cache-root">
|
|
243
|
+
{{ t('modal.providerCache.root') }}: {{ (providerCacheRecords && providerCacheRecords.root) || '~/.codexmate' }}
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<div class="provider-cache-toolbar">
|
|
247
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="loadProviderCacheRecords" :disabled="providerCacheLoading">
|
|
248
|
+
{{ providerCacheLoading ? t('modal.providerCache.refreshing') : t('modal.providerCache.refresh') }}
|
|
249
|
+
</button>
|
|
250
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="syncProviderCacheRecords" :disabled="providerCacheLoading || providerCacheSyncing">
|
|
251
|
+
{{ providerCacheSyncing ? t('modal.providerCache.syncing') : t('modal.providerCache.sync') }}
|
|
252
|
+
</button>
|
|
253
|
+
<span v-if="providerCacheLoadedAt" class="provider-cache-loaded-at">{{ t('modal.providerCache.loadedAt') }}: {{ providerCacheLoadedAt }}</span>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<div v-if="providerCacheError" class="state-message error provider-cache-error">
|
|
257
|
+
{{ providerCacheError }}
|
|
258
|
+
</div>
|
|
259
|
+
<div v-if="providerCacheSyncMessage" class="state-message provider-cache-sync-message">
|
|
260
|
+
{{ providerCacheSyncMessage }}
|
|
261
|
+
</div>
|
|
262
|
+
<div v-if="providerCacheLoading && !providerCacheLoadedOnce" class="state-message">
|
|
263
|
+
{{ t('modal.providerCache.loading') }}
|
|
264
|
+
</div>
|
|
265
|
+
<div v-else class="provider-cache-body">
|
|
266
|
+
<div class="provider-cache-groups">
|
|
267
|
+
<section v-for="group in getProviderCacheGroups()" :key="group.key" class="provider-cache-group">
|
|
268
|
+
<div class="provider-cache-group-header">
|
|
269
|
+
<div class="provider-cache-group-title">{{ group.label }}</div>
|
|
270
|
+
<div class="provider-cache-group-meta">{{ t('modal.providerCache.groupMeta', { count: group.existingCount || 0 }) }}</div>
|
|
271
|
+
</div>
|
|
272
|
+
<div v-if="!hasProviderCacheExistingFiles(group)" class="provider-cache-empty">
|
|
273
|
+
{{ t('modal.providerCache.empty') }}
|
|
274
|
+
</div>
|
|
275
|
+
<div v-else class="provider-cache-file-list">
|
|
276
|
+
<article v-for="file in getProviderCacheExistingFiles(group)" :key="getProviderCacheFileKey(file)" class="provider-cache-file">
|
|
277
|
+
<div class="provider-cache-file-header">
|
|
278
|
+
<div>
|
|
279
|
+
<div class="provider-cache-file-name">{{ file.name }}</div>
|
|
280
|
+
<div class="provider-cache-file-summary">{{ getProviderCacheFileSummary(file) }}</div>
|
|
281
|
+
</div>
|
|
282
|
+
<div class="provider-cache-file-meta">
|
|
283
|
+
<span>{{ formatProviderCacheFileSize(file.size) }}</span>
|
|
284
|
+
<span v-if="file.mtime">{{ file.mtime }}</span>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
<div class="provider-cache-file-path">{{ getProviderCacheFilePath(file) }}</div>
|
|
288
|
+
|
|
289
|
+
<div v-if="hasProviderCacheProviders(file)" class="provider-cache-provider-list">
|
|
290
|
+
<details v-for="(provider, providerIndex) in getProviderCacheFileProviders(file)" :key="provider.name || (getProviderCacheFileKey(file) + ':' + providerIndex)" class="provider-cache-provider" open>
|
|
291
|
+
<summary class="provider-cache-provider-summary">
|
|
292
|
+
<span class="provider-cache-provider-name">{{ provider.name || 'provider' }}</span>
|
|
293
|
+
<span class="provider-cache-provider-badges">
|
|
294
|
+
<span v-for="item in getProviderCacheProviderMeta(provider)" :key="item.label" class="provider-cache-provider-badge">
|
|
295
|
+
{{ item.label }}: {{ item.value }}
|
|
296
|
+
</span>
|
|
297
|
+
</span>
|
|
298
|
+
</summary>
|
|
299
|
+
<pre class="provider-cache-json provider-cache-json-compact">{{ getProviderCacheProviderText(provider) }}</pre>
|
|
300
|
+
</details>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<details class="provider-cache-raw" :open="!hasProviderCacheProviders(file) || file.ok === false">
|
|
304
|
+
<summary>{{ file.ok === false ? t('modal.providerCache.errorDetails') : t('modal.providerCache.rawJson') }}</summary>
|
|
305
|
+
<pre :class="['provider-cache-json', { error: file.ok === false }]">{{ getProviderCacheRecordText(file) }}</pre>
|
|
306
|
+
</details>
|
|
307
|
+
</article>
|
|
308
|
+
</div>
|
|
309
|
+
</section>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
|
|
313
|
+
<div class="btn-group provider-cache-footer">
|
|
314
|
+
<button class="btn btn-confirm" @click="closeProviderCacheModal">{{ t('common.close') }}</button>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
137
319
|
<!-- 添加Claude配置模态框 -->
|
|
138
320
|
<div v-if="showClaudeConfigModal" class="modal-overlay" @click.self="closeClaudeConfigModal">
|
|
139
321
|
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="add-claude-config-modal-title">
|
|
@@ -119,11 +119,11 @@
|
|
|
119
119
|
</div>
|
|
120
120
|
</div>
|
|
121
121
|
|
|
122
|
-
<div v-if="sessionsLoading" class="state-message">
|
|
122
|
+
<div v-if="sessionsLoading && sessionsList.length === 0" class="state-message">
|
|
123
123
|
{{ t('sessions.loadingList') }}
|
|
124
124
|
</div>
|
|
125
125
|
|
|
126
|
-
<div v-else-if="sessionsList.length === 0" class="session-empty">
|
|
126
|
+
<div v-else-if="!sessionsLoading && sessionsList.length === 0" class="session-empty">
|
|
127
127
|
{{ t('sessions.empty') }}
|
|
128
128
|
</div>
|
|
129
129
|
|
|
@@ -166,6 +166,26 @@
|
|
|
166
166
|
<input ref="codexImportInput" class="sr-only" type="file" accept=".zip" @change="handleCodexImportChange">
|
|
167
167
|
</section>
|
|
168
168
|
|
|
169
|
+
<section class="settings-card" :aria-label="t('settings.providerCache.title')">
|
|
170
|
+
<div class="settings-card-main">
|
|
171
|
+
<div class="settings-card-content">
|
|
172
|
+
<div class="settings-card-title">{{ t('settings.providerCache.title') }}</div>
|
|
173
|
+
<p class="settings-card-desc">{{ t('settings.providerCache.meta') }}</p>
|
|
174
|
+
<p class="settings-card-hint">{{ t('settings.providerCache.hint') }}</p>
|
|
175
|
+
<p v-if="providerCacheSyncMessage" class="settings-card-hint provider-cache-sync-message">{{ providerCacheSyncMessage }}</p>
|
|
176
|
+
<p v-if="providerCacheError" class="settings-card-hint form-error">{{ providerCacheError }}</p>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="settings-card-actions">
|
|
180
|
+
<button class="settings-card-action" @click="openProviderCacheModal({ forceRefresh: true })" :disabled="providerCacheLoading || providerCacheSyncing">
|
|
181
|
+
{{ providerCacheLoading ? t('settings.providerCache.loading') : t('settings.providerCache.open') }}
|
|
182
|
+
</button>
|
|
183
|
+
<button class="settings-card-action" @click="syncProviderCacheRecords" :disabled="providerCacheLoading || providerCacheSyncing">
|
|
184
|
+
{{ providerCacheSyncing ? t('settings.providerCache.syncing') : t('settings.providerCache.sync') }}
|
|
185
|
+
</button>
|
|
186
|
+
</div>
|
|
187
|
+
</section>
|
|
188
|
+
|
|
169
189
|
<section class="settings-card" :aria-label="t('settings.trashConfig.title')">
|
|
170
190
|
<div class="settings-card-main">
|
|
171
191
|
<div class="settings-card-content">
|