codexmate 0.0.44 → 0.0.45
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/package.json +1 -1
- package/web-ui/app.js +15 -1
- package/web-ui/index.html +1 -0
- package/web-ui/modules/app.computed.index.mjs +3 -1
- package/web-ui/modules/app.computed.main-tabs.mjs +3 -0
- package/web-ui/modules/app.computed.prompts.mjs +28 -0
- package/web-ui/modules/app.computed.session.mjs +23 -1
- package/web-ui/modules/app.methods.agents.mjs +50 -4
- package/web-ui/modules/app.methods.navigation.mjs +2 -1
- package/web-ui/modules/app.methods.session-actions.mjs +10 -0
- package/web-ui/modules/i18n/locales/en.mjs +24 -5
- package/web-ui/modules/i18n/locales/ja.mjs +24 -5
- package/web-ui/modules/i18n/locales/vi.mjs +31 -0
- package/web-ui/modules/i18n/locales/zh.mjs +24 -5
- package/web-ui/partials/index/layout-footer.html +1 -1
- package/web-ui/partials/index/layout-header.html +40 -0
- package/web-ui/partials/index/modal-config-template-agents.html +12 -13
- package/web-ui/partials/index/panel-config-claude.html +0 -6
- package/web-ui/partials/index/panel-config-codex.html +0 -5
- package/web-ui/partials/index/panel-prompts.html +100 -0
- package/web-ui/partials/index/panel-sessions.html +30 -10
- package/web-ui/partials/index/panel-usage.html +34 -18
- package/web-ui/res/web-ui-render.precompiled.js +465 -128
- package/web-ui/styles/modals-core.css +162 -0
- package/web-ui/styles/responsive.css +65 -5
- package/web-ui/styles/sessions-toolbar-trash.css +45 -10
- package/web-ui/styles/sessions-usage.css +31 -2
|
@@ -49,6 +49,8 @@ const zh = Object.freeze({
|
|
|
49
49
|
'common.apply': '应用',
|
|
50
50
|
'common.applying': '应用中...',
|
|
51
51
|
'common.confirming': '确认中...',
|
|
52
|
+
'common.preview': '预览',
|
|
53
|
+
'common.previewing': '预览中...',
|
|
52
54
|
'common.refreshFromText': '从文本刷新',
|
|
53
55
|
'common.backToEdit': '返回编辑',
|
|
54
56
|
'common.selectAll': '全选',
|
|
@@ -129,12 +131,14 @@ const zh = Object.freeze({
|
|
|
129
131
|
'tab.market': 'Skills',
|
|
130
132
|
'tab.plugins': '插件',
|
|
131
133
|
'tab.settings': '设置',
|
|
134
|
+
'tab.prompts': 'Prompts',
|
|
132
135
|
|
|
133
136
|
// Side rail section titles
|
|
134
137
|
'side.overview': '概览',
|
|
135
138
|
'side.docs': '文档',
|
|
136
139
|
'side.config': '配置',
|
|
137
140
|
'side.sessions': '会话',
|
|
141
|
+
'side.prompts': 'Prompts',
|
|
138
142
|
'side.plugins': '插件',
|
|
139
143
|
'side.system': '系统',
|
|
140
144
|
'side.orchestration': '任务',
|
|
@@ -164,6 +168,10 @@ const zh = Object.freeze({
|
|
|
164
168
|
'side.config.openclaw.meta': 'JSON5 / AGENTS',
|
|
165
169
|
'side.sessions.browser': '会话浏览',
|
|
166
170
|
'side.sessions.browser.meta': '浏览 / 导出 / 清理',
|
|
171
|
+
'side.prompts.agents': 'AGENTS.md',
|
|
172
|
+
'side.prompts.agents.meta': 'Codex 指令文件',
|
|
173
|
+
'side.prompts.claude': 'CLAUDE.md',
|
|
174
|
+
'side.prompts.claude.meta': 'Claude 指令文件',
|
|
167
175
|
'side.plugins.tools': '提示词工具',
|
|
168
176
|
'side.plugins.tools.meta': '模板 / 变量',
|
|
169
177
|
'side.plugins.templatesCount': '{count} 个模板',
|
|
@@ -182,6 +190,7 @@ const zh = Object.freeze({
|
|
|
182
190
|
'kicker.docs': 'Docs',
|
|
183
191
|
'kicker.trash': '回收站',
|
|
184
192
|
'kicker.settings': 'Settings',
|
|
193
|
+
'kicker.prompts': 'Prompts',
|
|
185
194
|
|
|
186
195
|
'title.dashboard': 'Dashboard / Doctor',
|
|
187
196
|
'title.config': '本地配置控制台',
|
|
@@ -192,6 +201,7 @@ const zh = Object.freeze({
|
|
|
192
201
|
'title.plugins': '插件与模板',
|
|
193
202
|
'title.docs': 'CLI 安装与文档',
|
|
194
203
|
'title.settings': '系统与数据设置',
|
|
204
|
+
'title.prompts': '指令文件编辑器',
|
|
195
205
|
|
|
196
206
|
'subtitle.dashboard': '聚合状态与诊断入口。',
|
|
197
207
|
'subtitle.config': '管理本地配置与模型。',
|
|
@@ -202,6 +212,9 @@ const zh = Object.freeze({
|
|
|
202
212
|
'subtitle.plugins': '管理模板化 prompt 与可复用插件。',
|
|
203
213
|
'subtitle.docs': '查看 CLI 安装命令与排障。',
|
|
204
214
|
'subtitle.settings': '管理下载、目录与回收站。',
|
|
215
|
+
'subtitle.prompts': '编辑 AGENTS.md 与 CLAUDE.md。',
|
|
216
|
+
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
217
|
+
'prompts.subTab.claude': 'CLAUDE.md (Claude)',
|
|
205
218
|
'dashboard.doctor.title': 'Doctor',
|
|
206
219
|
'dashboard.doctor.runChecks': '运行检查',
|
|
207
220
|
'dashboard.doctor.checking': '检查中...',
|
|
@@ -378,8 +391,13 @@ const zh = Object.freeze({
|
|
|
378
391
|
'toast.copy.empty': '没有可复制内容',
|
|
379
392
|
'toast.copy.ok': '已复制',
|
|
380
393
|
'toast.copy.fail': '复制失败',
|
|
394
|
+
'toast.link.fail': '无法生成链接',
|
|
381
395
|
'toast.save.ok': '已保存',
|
|
382
396
|
'toast.save.fail': '保存失败',
|
|
397
|
+
'toast.agents.saved.agents': 'AGENTS.md 已保存',
|
|
398
|
+
'toast.agents.saved.claudeMd': 'CLAUDE.md 已保存',
|
|
399
|
+
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md 已保存',
|
|
400
|
+
'toast.agents.saved.workspace': '工作区文件已保存: {name}',
|
|
383
401
|
'toast.delete.ok': '已删除',
|
|
384
402
|
'toast.delete.fail': '删除失败',
|
|
385
403
|
'toast.export.empty': '没有可导出内容',
|
|
@@ -468,7 +486,7 @@ const zh = Object.freeze({
|
|
|
468
486
|
'diff.hint.busy': '正在生成差异或应用中,操作暂不可用。',
|
|
469
487
|
'diff.hint.failedBack': '差异预览失败,请返回编辑后重试。',
|
|
470
488
|
'diff.hint.noChangesBack': '未检测到改动,可返回编辑继续修改或取消退出。',
|
|
471
|
-
'diff.hint.previewMode': '
|
|
489
|
+
'diff.hint.previewMode': '当前为预览模式,可点击”保存”写入或”返回编辑”继续修改。',
|
|
472
490
|
|
|
473
491
|
'modal.agents.export': '导出',
|
|
474
492
|
'modal.agents.copy': '复制',
|
|
@@ -477,13 +495,13 @@ const zh = Object.freeze({
|
|
|
477
495
|
'modal.agents.targetFile': '目标文件',
|
|
478
496
|
'modal.agents.contentLabel': 'AGENTS.md 内容',
|
|
479
497
|
'modal.agents.placeholder': '在这里编辑 AGENTS.md 内容',
|
|
480
|
-
'modal.agents.unsaved.previewModeHint': '
|
|
498
|
+
'modal.agents.unsaved.previewModeHint': '预览模式:当前改动尚未保存,只有点击”保存”后才会写入文件。',
|
|
481
499
|
'modal.agents.unsaved.detectedHint': '检测到未保存改动:关闭页面或应用前请先保存。',
|
|
482
500
|
'modal.agents.hint.shortcuts': '快捷键:Esc(差异预览时返回编辑,编辑时关闭窗口)。',
|
|
483
|
-
'modal.agents.hint.twoStepSave': '
|
|
501
|
+
'modal.agents.hint.twoStepSave': '保存需两步:先点击”预览”查看差异,再点击”保存”写入。',
|
|
484
502
|
'diff.tooLargeSkip': '内容过大,已跳过逐行差异预览',
|
|
485
|
-
'diff.viewHint.preview': '
|
|
486
|
-
'diff.viewHint.truncated': '
|
|
503
|
+
'diff.viewHint.preview': '当前为预览模式,可点击”保存”写入或”返回编辑”继续修改。',
|
|
504
|
+
'diff.viewHint.truncated': '内容过大,已跳过预览,可点击”保存”写入或”返回编辑”继续修改。',
|
|
487
505
|
|
|
488
506
|
// Skills modal
|
|
489
507
|
'modal.skills.title': 'Skills 管理',
|
|
@@ -623,6 +641,7 @@ const zh = Object.freeze({
|
|
|
623
641
|
'sessions.preview.importNative.failedWithReason': '导入原生目录失败:{reason}',
|
|
624
642
|
'sessions.preview.copyLink': '复制链接',
|
|
625
643
|
'sessions.preview.copyPath': '复制路径',
|
|
644
|
+
'sessions.preview.openLink': '打开链接',
|
|
626
645
|
'sessions.preview.loadingBody': '正在加载会话内容...',
|
|
627
646
|
'sessions.preview.emptyMsgs': '当前会话暂无可展示消息',
|
|
628
647
|
'sessions.preview.rendering': '正在渲染会话内容...',
|
|
@@ -93,6 +93,16 @@
|
|
|
93
93
|
:class="{ active: isMainTabNavActive('plugins') }"
|
|
94
94
|
@pointerdown="onMainTabPointerDown('plugins', $event)"
|
|
95
95
|
@click="onMainTabClick('plugins', $event)">{{ t('tab.plugins') }}</button>
|
|
96
|
+
<button type="button" class="top-tab"
|
|
97
|
+
id="tab-prompts"
|
|
98
|
+
role="tab"
|
|
99
|
+
data-main-tab="prompts"
|
|
100
|
+
:tabindex="mainTab === 'prompts' ? 0 : -1"
|
|
101
|
+
:aria-selected="mainTab === 'prompts'"
|
|
102
|
+
aria-controls="panel-prompts"
|
|
103
|
+
:class="{ active: isMainTabNavActive('prompts') }"
|
|
104
|
+
@pointerdown="onMainTabPointerDown('prompts', $event)"
|
|
105
|
+
@click="onMainTabClick('prompts', $event)">{{ t('tab.prompts') }}</button>
|
|
96
106
|
<button type="button" class="top-tab"
|
|
97
107
|
id="tab-settings"
|
|
98
108
|
role="tab"
|
|
@@ -215,6 +225,36 @@
|
|
|
215
225
|
</button>
|
|
216
226
|
</div>
|
|
217
227
|
|
|
228
|
+
<div class="side-section" role="navigation" :aria-label="t('side.prompts')">
|
|
229
|
+
<div class="side-section-title">{{ t('side.prompts') }}</div>
|
|
230
|
+
<button
|
|
231
|
+
id="side-tab-prompts-agents"
|
|
232
|
+
data-main-tab="prompts"
|
|
233
|
+
data-prompts-sub-tab="codex"
|
|
234
|
+
:aria-current="mainTab === 'prompts' && promptsSubTab === 'codex' ? 'page' : null"
|
|
235
|
+
:class="['side-item', { active: isMainTabNavActive('prompts') && promptsSubTab === 'codex' }]"
|
|
236
|
+
@pointerdown="onMainTabPointerDown('prompts', $event)"
|
|
237
|
+
@click="switchPromptsSubTab('codex'); onMainTabClick('prompts')">
|
|
238
|
+
<div class="side-item-title">{{ t('side.prompts.agents') }}</div>
|
|
239
|
+
<div class="side-item-meta">
|
|
240
|
+
<span>{{ t('side.prompts.agents.meta') }}</span>
|
|
241
|
+
</div>
|
|
242
|
+
</button>
|
|
243
|
+
<button
|
|
244
|
+
id="side-tab-prompts-claude"
|
|
245
|
+
data-main-tab="prompts"
|
|
246
|
+
data-prompts-sub-tab="claude-md"
|
|
247
|
+
:aria-current="mainTab === 'prompts' && promptsSubTab === 'claude-md' ? 'page' : null"
|
|
248
|
+
:class="['side-item', { active: isMainTabNavActive('prompts') && promptsSubTab === 'claude-md' }]"
|
|
249
|
+
@pointerdown="onMainTabPointerDown('prompts', $event)"
|
|
250
|
+
@click="switchPromptsSubTab('claude-md'); onMainTabClick('prompts')">
|
|
251
|
+
<div class="side-item-title">{{ t('side.prompts.claude') }}</div>
|
|
252
|
+
<div class="side-item-meta">
|
|
253
|
+
<span>{{ t('side.prompts.claude.meta') }}</span>
|
|
254
|
+
</div>
|
|
255
|
+
</button>
|
|
256
|
+
</div>
|
|
257
|
+
|
|
218
258
|
<div class="side-section" role="navigation" :aria-label="t('side.sessions')">
|
|
219
259
|
<div class="side-section-title">{{ t('side.sessions') }}</div>
|
|
220
260
|
<button
|
|
@@ -102,6 +102,18 @@
|
|
|
102
102
|
:disabled="agentsLoading || agentsSaving || agentsDiffVisible">
|
|
103
103
|
{{ t('common.paste') }}
|
|
104
104
|
</button>
|
|
105
|
+
<span class="prompts-editor-actions-sep"></span>
|
|
106
|
+
<button class="btn-mini" @click="closeAgentsModal" :disabled="agentsSaving || agentsDiffLoading">{{ t('common.cancel') }}</button>
|
|
107
|
+
<button
|
|
108
|
+
v-if="agentsDiffVisible"
|
|
109
|
+
class="btn-mini"
|
|
110
|
+
@click="resetAgentsDiffState"
|
|
111
|
+
:disabled="agentsSaving || agentsDiffLoading">
|
|
112
|
+
{{ t('common.backToEdit') }}
|
|
113
|
+
</button>
|
|
114
|
+
<button class="btn-mini btn-confirm-mini" @click="applyAgentsContent" :disabled="agentsSaving || agentsLoading || agentsDiffLoading || (agentsDiffVisible && !agentsDiffHasChanges)">
|
|
115
|
+
{{ agentsSaving ? (agentsDiffVisible ? t('common.saving') : t('common.previewing')) : (agentsDiffVisible ? t('common.save') : t('common.preview')) }}
|
|
116
|
+
</button>
|
|
105
117
|
</div>
|
|
106
118
|
</div>
|
|
107
119
|
|
|
@@ -168,18 +180,5 @@
|
|
|
168
180
|
|
|
169
181
|
</div>
|
|
170
182
|
|
|
171
|
-
<div class="btn-group modal-editor-footer">
|
|
172
|
-
<button class="btn btn-cancel" @click="closeAgentsModal" :disabled="agentsSaving || agentsDiffLoading">{{ t('common.cancel') }}</button>
|
|
173
|
-
<button
|
|
174
|
-
v-if="agentsDiffVisible"
|
|
175
|
-
class="btn"
|
|
176
|
-
@click="resetAgentsDiffState"
|
|
177
|
-
:disabled="agentsSaving || agentsDiffLoading">
|
|
178
|
-
{{ t('common.backToEdit') }}
|
|
179
|
-
</button>
|
|
180
|
-
<button class="btn btn-confirm" @click="applyAgentsContent" :disabled="agentsSaving || agentsLoading || agentsDiffLoading || (agentsDiffVisible && !agentsDiffHasChanges)">
|
|
181
|
-
{{ agentsSaving ? (agentsDiffVisible ? t('common.applying') : t('common.confirming')) : (agentsDiffVisible ? t('common.apply') : t('common.confirm')) }}
|
|
182
|
-
</button>
|
|
183
|
-
</div>
|
|
184
183
|
</div>
|
|
185
184
|
</div>
|
|
@@ -108,12 +108,6 @@
|
|
|
108
108
|
<button class="btn-tool btn-template-editor" @click="openClaudeConfigTemplateEditor" :disabled="loading || !!initError">{{ t('config.template.openEditor') }}</button>
|
|
109
109
|
</div>
|
|
110
110
|
|
|
111
|
-
<div class="selector-section">
|
|
112
|
-
<div class="selector-header"><span class="selector-title">CLAUDE.md</span></div>
|
|
113
|
-
<button class="btn-tool" @click="openClaudeMdEditor" :disabled="loading || !!initError || agentsLoading">{{ agentsLoading ? t('config.modelLoading') : t('claude.md.open') }}</button>
|
|
114
|
-
<div class="config-template-hint">{{ t('claude.md.hint') }}</div>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
111
|
<div class="selector-section">
|
|
118
112
|
<div class="selector-header"><span class="selector-title">{{ t('config.health.title') }}</span></div>
|
|
119
113
|
<button class="btn-tool" @click="runHealthCheck" :disabled="healthCheckLoading || loading || !!initError">{{ healthCheckLoading ? t('config.health.running') : t('config.health.run') }}</button>
|
|
@@ -61,11 +61,6 @@
|
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
63
|
|
|
64
|
-
<div class="selector-section">
|
|
65
|
-
<div class="selector-header"><span class="selector-title">AGENTS.md</span></div>
|
|
66
|
-
<button class="btn-tool" @click="openAgentsEditor" :disabled="loading || !!initError || agentsLoading">{{ agentsLoading ? t('config.modelLoading') : t('config.agents.open') }}</button>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
64
|
<div class="selector-section">
|
|
70
65
|
<div class="selector-header">
|
|
71
66
|
<span class="selector-title">{{ t('config.models') }}</span>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!-- Prompts editor -->
|
|
2
|
+
<div
|
|
3
|
+
v-if="mainTab === 'prompts'"
|
|
4
|
+
class="mode-content mode-cards"
|
|
5
|
+
id="panel-prompts"
|
|
6
|
+
role="tabpanel"
|
|
7
|
+
aria-labelledby="tab-prompts">
|
|
8
|
+
<div class="segmented-control">
|
|
9
|
+
<button type="button" :class="['segment', { active: promptsSubTab === 'codex' }]" @click="switchPromptsSubTab('codex')">{{ t('prompts.subTab.codex') }}</button>
|
|
10
|
+
<button type="button" :class="['segment', { active: promptsSubTab === 'claude-md' }]" @click="switchPromptsSubTab('claude-md')">{{ t('prompts.subTab.claude') }}</button>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="prompts-editor">
|
|
14
|
+
<div class="prompts-editor-toolbar">
|
|
15
|
+
<div class="form-hint">
|
|
16
|
+
{{ agentsPath || t('common.notLoaded') }}
|
|
17
|
+
<span v-if="agentsPath">
|
|
18
|
+
({{ agentsExists ? t('common.exists') : t('common.notExistsWillCreateOnSave') }})
|
|
19
|
+
</span>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="prompts-editor-actions">
|
|
22
|
+
<div class="prompts-editor-group prompts-editor-group--secondary">
|
|
23
|
+
<button
|
|
24
|
+
class="btn-mini"
|
|
25
|
+
@click="exportAgentsContent"
|
|
26
|
+
:disabled="agentsLoading">
|
|
27
|
+
{{ t('modal.agents.export') }}
|
|
28
|
+
</button>
|
|
29
|
+
<button
|
|
30
|
+
class="btn-mini"
|
|
31
|
+
@click="copyAgentsContent"
|
|
32
|
+
:disabled="agentsLoading">
|
|
33
|
+
{{ t('modal.agents.copy') }}
|
|
34
|
+
</button>
|
|
35
|
+
<button
|
|
36
|
+
class="btn-mini"
|
|
37
|
+
@click="pasteAgentsContent"
|
|
38
|
+
:disabled="agentsLoading || agentsSaving || agentsDiffVisible">
|
|
39
|
+
{{ t('common.paste') }}
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="prompts-editor-group prompts-editor-group--workflow">
|
|
43
|
+
<button class="btn-mini" @click="loadPromptsContent" :disabled="agentsSaving || agentsDiffLoading">{{ t('common.cancel') }}</button>
|
|
44
|
+
<button
|
|
45
|
+
v-if="agentsDiffVisible"
|
|
46
|
+
class="btn-mini"
|
|
47
|
+
@click="resetAgentsDiffState"
|
|
48
|
+
:disabled="agentsSaving || agentsDiffLoading">
|
|
49
|
+
{{ t('common.backToEdit') }}
|
|
50
|
+
</button>
|
|
51
|
+
<button class="btn-mini btn-confirm-mini" @click="applyAgentsContent" :disabled="agentsSaving || agentsLoading || agentsDiffLoading || (!agentsDiffVisible && !hasAgentsContentChanged()) || (agentsDiffVisible && !agentsDiffHasChanges)">
|
|
52
|
+
{{ agentsSaving ? (agentsDiffVisible ? t('common.saving') : t('common.previewing')) : (agentsDiffVisible ? t('common.save') : t('common.preview')) }}
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="form-group">
|
|
59
|
+
<div v-if="agentsDiffVisible">
|
|
60
|
+
<div
|
|
61
|
+
v-if="!agentsDiffLoading && !agentsDiffError && !agentsDiffTruncated && (agentsDiffStats.added || agentsDiffStats.removed)"
|
|
62
|
+
class="agents-diff-summary">
|
|
63
|
+
<span class="agents-diff-stat add">+{{ agentsDiffStats.added }}</span>
|
|
64
|
+
<span class="agents-diff-stat del">-{{ agentsDiffStats.removed }}</span>
|
|
65
|
+
</div>
|
|
66
|
+
<div v-if="agentsDiffLoading" class="state-message">{{ t('diff.generating') }}</div>
|
|
67
|
+
<div v-else-if="agentsDiffError" class="state-message error">{{ agentsDiffError }}</div>
|
|
68
|
+
<div v-else-if="agentsDiffTruncated" class="agents-diff-empty">{{ t('diff.tooLargeSkip') }}</div>
|
|
69
|
+
<div v-else-if="!agentsDiffHasChanges" class="agents-diff-empty">{{ t('diff.noChanges') }}</div>
|
|
70
|
+
<div v-else class="agents-diff-view agents-diff-editor">
|
|
71
|
+
<div
|
|
72
|
+
v-for="(line, index) in agentsDiffLines"
|
|
73
|
+
:key="line.key || (line.type + '-' + index)"
|
|
74
|
+
:class="['agents-diff-line', line.type]">
|
|
75
|
+
<span class="agents-diff-line-sign">
|
|
76
|
+
{{ line.type === 'add' ? '+' : (line.type === 'del' ? '-' : ' ') }}
|
|
77
|
+
</span>
|
|
78
|
+
<span class="agents-diff-line-text">{{ line.value }}</span>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
<div :class="['editor-frame', { 'editor-frame--loading': agentsLoading }]">
|
|
83
|
+
<div v-if="agentsLoading" class="editor-skeleton">
|
|
84
|
+
<div class="skeleton-line" v-for="i in 6" :key="i"></div>
|
|
85
|
+
</div>
|
|
86
|
+
<textarea
|
|
87
|
+
v-model="agentsContent"
|
|
88
|
+
class="form-input template-editor"
|
|
89
|
+
spellcheck="false"
|
|
90
|
+
:readonly="agentsLoading || agentsSaving || agentsDiffVisible"
|
|
91
|
+
@input="onAgentsContentInput"
|
|
92
|
+
:placeholder="t(promptsSubTab === 'claude-md' ? 'modal.agents.placeholder.claudeMd' : 'modal.agents.placeholder')"></textarea>
|
|
93
|
+
</div>
|
|
94
|
+
<div v-if="promptsContextHint" :class="['prompts-context-hint', { 'prompts-context-hint--warn': promptsContextHint.warn }]">
|
|
95
|
+
{{ promptsContextHint.text }}
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
@@ -219,33 +219,53 @@
|
|
|
219
219
|
</div>
|
|
220
220
|
</div>
|
|
221
221
|
<div class="session-actions">
|
|
222
|
-
<button class="btn-session-refresh" @click="loadActiveSessionDetail" :disabled="sessionDetailLoading || !activeSession"
|
|
223
|
-
|
|
222
|
+
<button class="btn-session-refresh" @click="loadActiveSessionDetail" :disabled="sessionDetailLoading || !activeSession"
|
|
223
|
+
:title="sessionDetailLoading ? t('sessions.preview.loading') : t('sessions.preview.refresh')"
|
|
224
|
+
:aria-label="sessionDetailLoading ? t('sessions.preview.loading') : t('sessions.preview.refresh')">
|
|
225
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 8a5.5 5.5 0 0 1 9.4-3.8"/><path d="M13.5 8a5.5 5.5 0 0 1-9.4 3.8"/><polyline points="2.5 2 2.5 5 5.5 5"/><polyline points="13.5 14 13.5 11 10.5 11"/></svg>
|
|
224
226
|
</button>
|
|
225
227
|
<button
|
|
226
228
|
v-if="isDeleteAvailable(activeSession)"
|
|
227
229
|
class="btn-session-delete"
|
|
228
230
|
@click="deleteSession(activeSession)"
|
|
229
|
-
:disabled="!activeSession || sessionsLoading || sessionDeleting[getSessionExportKey(activeSession)]"
|
|
230
|
-
|
|
231
|
+
:disabled="!activeSession || sessionsLoading || sessionDeleting[getSessionExportKey(activeSession)]"
|
|
232
|
+
:title="(activeSession && sessionDeleting[getSessionExportKey(activeSession)]) ? (sessionTrashEnabled === false ? t('sessions.preview.deleting') : t('sessions.preview.moving')) : (sessionTrashEnabled === false ? t('sessions.preview.deleteHard') : t('sessions.preview.moveToTrash'))"
|
|
233
|
+
:aria-label="(activeSession && sessionDeleting[getSessionExportKey(activeSession)]) ? (sessionTrashEnabled === false ? t('sessions.preview.deleting') : t('sessions.preview.moving')) : (sessionTrashEnabled === false ? t('sessions.preview.deleteHard') : t('sessions.preview.moveToTrash'))">
|
|
234
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 4 4 4 13 4"/><path d="M5.5 4V2.5a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1V4"/><path d="M12 4v9.5a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 4 13.5V4"/></svg>
|
|
231
235
|
</button>
|
|
232
236
|
<button
|
|
233
237
|
class="btn-session-export"
|
|
234
238
|
@click="exportSession(activeSession)"
|
|
235
|
-
:disabled="!activeSession || sessionExporting[getSessionExportKey(activeSession)]"
|
|
236
|
-
|
|
239
|
+
:disabled="!activeSession || sessionExporting[getSessionExportKey(activeSession)]"
|
|
240
|
+
:title="(activeSession && sessionExporting[getSessionExportKey(activeSession)]) ? t('sessions.preview.exporting') : t('sessions.preview.export')"
|
|
241
|
+
:aria-label="(activeSession && sessionExporting[getSessionExportKey(activeSession)]) ? t('sessions.preview.exporting') : t('sessions.preview.export')">
|
|
242
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v8"/><polyline points="4 7 8 10.5 12 7"/><path d="M2.5 12v1.5a1 1 0 0 0 1 1h9a1 1 0 0 0 1-1V12"/></svg>
|
|
237
243
|
</button>
|
|
244
|
+
<div class="session-link-group">
|
|
238
245
|
<button
|
|
239
246
|
class="btn-session-open"
|
|
240
247
|
@click="copySessionLink(activeSession)"
|
|
241
|
-
:disabled="!activeSession"
|
|
242
|
-
|
|
248
|
+
:disabled="!activeSession || !canBuildStandaloneUrl(activeSession)"
|
|
249
|
+
:title="t('sessions.preview.copyLink')"
|
|
250
|
+
:aria-label="t('sessions.preview.copyLink')">
|
|
251
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2.5" width="4" height="2" rx="1"/><path d="M4.5 4h7a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5"/><line x1="6" y1="7.5" x2="10" y2="7.5"/><line x1="6" y1="10" x2="10" y2="10"/></svg>
|
|
243
252
|
</button>
|
|
253
|
+
<button
|
|
254
|
+
class="btn-session-open"
|
|
255
|
+
@click="openSessionLink(activeSession)"
|
|
256
|
+
:disabled="!activeSession || !canBuildStandaloneUrl(activeSession)"
|
|
257
|
+
:title="t('sessions.preview.openLink')"
|
|
258
|
+
:aria-label="t('sessions.preview.openLink')">
|
|
259
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2h-8.5A1.5 1.5 0 0 0 2 3.5v8A1.5 1.5 0 0 0 3.5 13h8a1.5 1.5 0 0 0 1.5-1.5v-3"/><path d="M13 2v4h-4"/><path d="M13 2L7 8"/></svg>
|
|
260
|
+
</button>
|
|
261
|
+
</div>
|
|
244
262
|
<button
|
|
245
263
|
class="btn-session-open"
|
|
246
264
|
@click="copySessionPath(activeSession)"
|
|
247
|
-
:disabled="!activeSession || !getSessionFilePath(activeSession)"
|
|
248
|
-
|
|
265
|
+
:disabled="!activeSession || !getSessionFilePath(activeSession)"
|
|
266
|
+
:title="t('sessions.preview.copyPath')"
|
|
267
|
+
:aria-label="t('sessions.preview.copyPath')">
|
|
268
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2.5" width="4" height="2" rx="1"/><path d="M4.5 4h7a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5"/><line x1="6" y1="7.5" x2="10" y2="7.5"/><line x1="6" y1="10" x2="10" y2="10"/></svg>
|
|
249
269
|
</button>
|
|
250
270
|
</div>
|
|
251
271
|
</div>
|
|
@@ -75,26 +75,42 @@
|
|
|
75
75
|
<section v-if="sessionUsageWave.points && sessionUsageWave.points.length" class="usage-wave-section">
|
|
76
76
|
<div class="usage-card-title">{{ t('usage.daily.title') }}</div>
|
|
77
77
|
<div class="usage-wave-container">
|
|
78
|
-
<
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
</linearGradient>
|
|
84
|
-
</defs>
|
|
85
|
-
<path :d="sessionUsageWave.areaPath" :fill="'url(#wave-gradient-' + sessionsUsageTimeRange + ')'" class="usage-wave-area"/>
|
|
86
|
-
<path :d="sessionUsageWave.linePath" fill="none" :stroke="'var(--color-brand)'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="usage-wave-line"/>
|
|
87
|
-
<line v-if="sessionsUsageSelectedDay" x1="0" :x2="sessionUsageWave.width" :y1="sessionUsageWave.hoverY" :y2="sessionUsageWave.hoverY" stroke="currentColor" stroke-width="1" stroke-dasharray="4 4" opacity="0.5" class="usage-wave-hover-line"/>
|
|
88
|
-
<circle v-if="sessionsUsageSelectedDay" :cx="sessionUsageWave.hoverX" :cy="sessionUsageWave.hoverY" r="5" :fill="'var(--color-surface)'" :stroke="'var(--color-brand)'" stroke-width="2.5" class="usage-wave-hover-point"/>
|
|
89
|
-
</svg>
|
|
90
|
-
<div class="usage-wave-labels">
|
|
91
|
-
<span v-for="label in sessionUsageWave.labels" :key="label.key"
|
|
92
|
-
class="usage-wave-label"
|
|
93
|
-
:class="{ active: sessionsUsageSelectedDay === label.key }"
|
|
94
|
-
@click="selectSessionsUsageDay(label.key)">
|
|
95
|
-
{{ label.text }}
|
|
78
|
+
<div class="usage-wave-yaxis">
|
|
79
|
+
<span v-for="tick in sessionUsageWave.yTicks" :key="tick.value"
|
|
80
|
+
class="usage-wave-ytick"
|
|
81
|
+
:style="{ bottom: tick.percent + '%' }">
|
|
82
|
+
{{ tick.label }}
|
|
96
83
|
</span>
|
|
97
84
|
</div>
|
|
85
|
+
<div class="usage-wave-chart-area">
|
|
86
|
+
<svg class="usage-wave-chart" viewBox="0 0 800 140" preserveAspectRatio="none">
|
|
87
|
+
<defs>
|
|
88
|
+
<linearGradient :id="'wave-gradient-' + sessionsUsageTimeRange" x1="0" y1="0" x2="0" y2="1">
|
|
89
|
+
<stop offset="0%" :stop-color="'var(--color-brand)'" stop-opacity="0.35"/>
|
|
90
|
+
<stop offset="100%" :stop-color="'var(--color-brand)'" stop-opacity="0"/>
|
|
91
|
+
</linearGradient>
|
|
92
|
+
</defs>
|
|
93
|
+
<line v-for="tick in sessionUsageWave.yTicks" :key="'g-' + tick.value"
|
|
94
|
+
x1="0" :x2="sessionUsageWave.width"
|
|
95
|
+
:y1="tick.y" :y2="tick.y"
|
|
96
|
+
stroke="currentColor" stroke-width="0.5" opacity="0.12"
|
|
97
|
+
class="usage-wave-gridline"/>
|
|
98
|
+
<path :d="sessionUsageWave.areaPath" :fill="'url(#wave-gradient-' + sessionsUsageTimeRange + ')'" class="usage-wave-area"/>
|
|
99
|
+
<path :d="sessionUsageWave.linePath" fill="none" :stroke="'var(--color-brand)'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="usage-wave-line"/>
|
|
100
|
+
<line v-if="sessionsUsageSelectedDay" x1="0" :x2="sessionUsageWave.width" :y1="sessionUsageWave.hoverY" :y2="sessionUsageWave.hoverY" stroke="currentColor" stroke-width="1" stroke-dasharray="4 4" opacity="0.5" class="usage-wave-hover-line"/>
|
|
101
|
+
<circle v-if="sessionsUsageSelectedDay" :cx="sessionUsageWave.hoverX" :cy="sessionUsageWave.hoverY" r="5" :fill="'var(--color-surface)'" :stroke="'var(--color-brand)'" stroke-width="2.5" class="usage-wave-hover-point"/>
|
|
102
|
+
</svg>
|
|
103
|
+
<div class="usage-wave-labels">
|
|
104
|
+
<button v-for="label in sessionUsageWave.labels" :key="label.key"
|
|
105
|
+
type="button"
|
|
106
|
+
class="usage-wave-label"
|
|
107
|
+
:class="{ active: sessionsUsageSelectedDay === label.key }"
|
|
108
|
+
:aria-pressed="sessionsUsageSelectedDay === label.key"
|
|
109
|
+
@click="selectSessionsUsageDay(label.key)">
|
|
110
|
+
{{ label.text }}
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
98
114
|
</div>
|
|
99
115
|
<div v-if="sessionsUsageSelectedDaySummary" class="usage-daydetail">
|
|
100
116
|
<div class="usage-daydetail-header">
|