codexmate 0.0.24 → 0.0.25
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 +28 -6
- package/README.zh.md +29 -7
- package/cli/builtin-proxy.js +35 -0
- package/cli/claude-proxy.js +24 -0
- package/cli/import-skills-url.js +23 -1
- package/cli/openai-bridge.js +51 -4
- package/cli/session-usage.js +8 -2
- package/cli.js +1543 -117
- package/lib/automation.js +404 -0
- package/lib/cli-path-utils.js +21 -5
- package/lib/cli-sessions.js +32 -1
- package/lib/download-artifacts.js +17 -2
- package/lib/mcp-stdio.js +13 -0
- package/package.json +2 -5
- package/web-ui/app.js +6 -3
- package/web-ui/logic.sessions.mjs +2 -2
- package/web-ui/modules/app.computed.dashboard.mjs +2 -0
- package/web-ui/modules/app.computed.session.mjs +17 -0
- package/web-ui/modules/app.methods.install.mjs +28 -0
- package/web-ui/modules/app.methods.session-actions.mjs +8 -1
- package/web-ui/modules/app.methods.session-browser.mjs +28 -4
- package/web-ui/modules/app.methods.session-trash.mjs +4 -2
- package/web-ui/modules/i18n.dict.mjs +24 -8
- package/web-ui/partials/index/layout-header.html +12 -2
- package/web-ui/partials/index/panel-sessions.html +4 -2
- package/web-ui/partials/index/panel-usage.html +7 -0
- package/web-ui/styles/controls-forms.css +49 -2
- package/web-ui/styles/layout-shell.css +1 -0
- package/web-ui/styles/responsive.css +0 -2
- package/web-ui/styles/sessions-list.css +2 -4
- package/web-ui/styles/sessions-toolbar-trash.css +4 -4
- package/web-ui/styles/sessions-usage.css +24 -0
- /package/{res → web-ui/res}/json5.min.js +0 -0
- /package/{res → web-ui/res}/logo-pack.webp +0 -0
- /package/{res → web-ui/res}/vue.global.prod.js +0 -0
|
@@ -104,6 +104,16 @@ export function createInstallMethods() {
|
|
|
104
104
|
update: '',
|
|
105
105
|
uninstall: ''
|
|
106
106
|
},
|
|
107
|
+
codebuddy: {
|
|
108
|
+
install: '',
|
|
109
|
+
update: '',
|
|
110
|
+
uninstall: ''
|
|
111
|
+
},
|
|
112
|
+
gemini: {
|
|
113
|
+
install: '',
|
|
114
|
+
update: '',
|
|
115
|
+
uninstall: ''
|
|
116
|
+
},
|
|
107
117
|
codex: {
|
|
108
118
|
install: '',
|
|
109
119
|
update: '',
|
|
@@ -114,6 +124,12 @@ export function createInstallMethods() {
|
|
|
114
124
|
matrix.claude.install = 'pnpm add -g @anthropic-ai/claude-code';
|
|
115
125
|
matrix.claude.update = 'pnpm up -g @anthropic-ai/claude-code';
|
|
116
126
|
matrix.claude.uninstall = 'pnpm remove -g @anthropic-ai/claude-code';
|
|
127
|
+
matrix.codebuddy.install = 'pnpm add -g @tencent-ai/codebuddy-code';
|
|
128
|
+
matrix.codebuddy.update = 'pnpm up -g @tencent-ai/codebuddy-code';
|
|
129
|
+
matrix.codebuddy.uninstall = 'pnpm remove -g @tencent-ai/codebuddy-code';
|
|
130
|
+
matrix.gemini.install = 'pnpm add -g @google/gemini-cli';
|
|
131
|
+
matrix.gemini.update = 'pnpm up -g @google/gemini-cli';
|
|
132
|
+
matrix.gemini.uninstall = 'pnpm remove -g @google/gemini-cli';
|
|
117
133
|
matrix.codex.install = `pnpm add -g ${codexInstallPackage}`;
|
|
118
134
|
matrix.codex.update = `pnpm up -g ${codexPackage}`;
|
|
119
135
|
matrix.codex.uninstall = `pnpm remove -g ${codexPackage}`;
|
|
@@ -123,6 +139,12 @@ export function createInstallMethods() {
|
|
|
123
139
|
matrix.claude.install = 'bun add -g @anthropic-ai/claude-code';
|
|
124
140
|
matrix.claude.update = 'bun update -g @anthropic-ai/claude-code';
|
|
125
141
|
matrix.claude.uninstall = 'bun remove -g @anthropic-ai/claude-code';
|
|
142
|
+
matrix.codebuddy.install = 'bun add -g @tencent-ai/codebuddy-code';
|
|
143
|
+
matrix.codebuddy.update = 'bun update -g @tencent-ai/codebuddy-code';
|
|
144
|
+
matrix.codebuddy.uninstall = 'bun remove -g @tencent-ai/codebuddy-code';
|
|
145
|
+
matrix.gemini.install = 'bun add -g @google/gemini-cli';
|
|
146
|
+
matrix.gemini.update = 'bun update -g @google/gemini-cli';
|
|
147
|
+
matrix.gemini.uninstall = 'bun remove -g @google/gemini-cli';
|
|
126
148
|
matrix.codex.install = `bun add -g ${codexInstallPackage}`;
|
|
127
149
|
matrix.codex.update = `bun update -g ${codexPackage}`;
|
|
128
150
|
matrix.codex.uninstall = `bun remove -g ${codexPackage}`;
|
|
@@ -131,6 +153,12 @@ export function createInstallMethods() {
|
|
|
131
153
|
matrix.claude.install = 'npm install -g @anthropic-ai/claude-code';
|
|
132
154
|
matrix.claude.update = 'npm update -g @anthropic-ai/claude-code';
|
|
133
155
|
matrix.claude.uninstall = 'npm uninstall -g @anthropic-ai/claude-code';
|
|
156
|
+
matrix.codebuddy.install = 'npm install -g @tencent-ai/codebuddy-code';
|
|
157
|
+
matrix.codebuddy.update = 'npm update -g @tencent-ai/codebuddy-code';
|
|
158
|
+
matrix.codebuddy.uninstall = 'npm uninstall -g @tencent-ai/codebuddy-code';
|
|
159
|
+
matrix.gemini.install = 'npm install -g @google/gemini-cli';
|
|
160
|
+
matrix.gemini.update = 'npm update -g @google/gemini-cli';
|
|
161
|
+
matrix.gemini.uninstall = 'npm uninstall -g @google/gemini-cli';
|
|
134
162
|
matrix.codex.install = `npm install -g ${codexInstallPackage}`;
|
|
135
163
|
matrix.codex.update = platform === 'termux'
|
|
136
164
|
? `npm install -g ${codexInstallPackage}`
|
|
@@ -117,7 +117,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
117
117
|
if (!session) return false;
|
|
118
118
|
const source = String(session.source || '').trim().toLowerCase();
|
|
119
119
|
const sessionId = typeof session.sessionId === 'string' ? session.sessionId.trim() : '';
|
|
120
|
-
return source === 'codex' && !!sessionId;
|
|
120
|
+
return (source === 'codex' || source === 'codebuddy' || source === 'gemini') && !!sessionId;
|
|
121
121
|
},
|
|
122
122
|
|
|
123
123
|
isCloneAvailable(session) {
|
|
@@ -138,8 +138,15 @@ export function createSessionActionMethods(options = {}) {
|
|
|
138
138
|
},
|
|
139
139
|
|
|
140
140
|
buildResumeCommand(session) {
|
|
141
|
+
const source = session && session.source ? String(session.source).trim().toLowerCase() : '';
|
|
141
142
|
const sessionId = session && session.sessionId ? String(session.sessionId).trim() : '';
|
|
142
143
|
const arg = this.quoteResumeArg(sessionId);
|
|
144
|
+
if (source === 'codebuddy') {
|
|
145
|
+
return `codebuddy -r ${arg}`;
|
|
146
|
+
}
|
|
147
|
+
if (source === 'gemini') {
|
|
148
|
+
return `gemini -r ${arg}`;
|
|
149
|
+
}
|
|
143
150
|
if (this.sessionResumeWithYolo) {
|
|
144
151
|
return `codex --yolo resume ${arg}`;
|
|
145
152
|
}
|
|
@@ -127,7 +127,9 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
127
127
|
},
|
|
128
128
|
|
|
129
129
|
syncSessionPathOptionsForSource(source, nextOptions, mergeWithExisting = false) {
|
|
130
|
-
const targetSource = source === 'claude'
|
|
130
|
+
const targetSource = source === 'claude'
|
|
131
|
+
? 'claude'
|
|
132
|
+
: (source === 'gemini' ? 'gemini' : (source === 'all' ? 'all' : 'codex'));
|
|
131
133
|
const current = Array.isArray(this.sessionPathOptionsMap[targetSource])
|
|
132
134
|
? this.sessionPathOptionsMap[targetSource]
|
|
133
135
|
: [];
|
|
@@ -142,7 +144,9 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
142
144
|
},
|
|
143
145
|
|
|
144
146
|
refreshSessionPathOptions(source) {
|
|
145
|
-
const targetSource = source === 'claude'
|
|
147
|
+
const targetSource = source === 'claude'
|
|
148
|
+
? 'claude'
|
|
149
|
+
: (source === 'gemini' ? 'gemini' : (source === 'all' ? 'all' : 'codex'));
|
|
146
150
|
const base = Array.isArray(this.sessionPathOptionsMap[targetSource])
|
|
147
151
|
? [...this.sessionPathOptionsMap[targetSource]]
|
|
148
152
|
: [];
|
|
@@ -164,7 +168,9 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
164
168
|
},
|
|
165
169
|
|
|
166
170
|
async loadSessionPathOptions(options = {}) {
|
|
167
|
-
const source = options.source === 'claude'
|
|
171
|
+
const source = options.source === 'claude'
|
|
172
|
+
? 'claude'
|
|
173
|
+
: (options.source === 'gemini' ? 'gemini' : (options.source === 'all' ? 'all' : 'codex'));
|
|
168
174
|
const forceRefresh = !!options.forceRefresh;
|
|
169
175
|
const loaded = !!this.sessionPathOptionsLoadedMap[source];
|
|
170
176
|
if (!forceRefresh && loaded) {
|
|
@@ -252,6 +258,9 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
252
258
|
const urlState = readSessionsFilterUrlState();
|
|
253
259
|
if (urlState) {
|
|
254
260
|
applySessionsFilterUrlState(this, urlState);
|
|
261
|
+
if (this.mainTab === 'sessions' && typeof this.loadSessions === 'function') {
|
|
262
|
+
void this.loadSessions();
|
|
263
|
+
}
|
|
255
264
|
return;
|
|
256
265
|
}
|
|
257
266
|
const sourceCache = localStorage.getItem('codexmateSessionFilterSource');
|
|
@@ -266,6 +275,16 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
266
275
|
this.sessionRoleFilter = normalizeSessionRoleFilter(roleCache);
|
|
267
276
|
this.sessionTimePreset = normalizeSessionTimePreset(timeCache);
|
|
268
277
|
this.refreshSessionPathOptions(this.sessionFilterSource);
|
|
278
|
+
if (this.mainTab === 'sessions' && typeof this.loadSessions === 'function') {
|
|
279
|
+
const shouldReload = cached.source !== 'all'
|
|
280
|
+
|| !!cached.pathFilter
|
|
281
|
+
|| !!(this.sessionQuery && isSessionQueryEnabled(cached.source))
|
|
282
|
+
|| (this.sessionRoleFilter && this.sessionRoleFilter !== 'all')
|
|
283
|
+
|| (this.sessionTimePreset && this.sessionTimePreset !== 'all');
|
|
284
|
+
if (shouldReload) {
|
|
285
|
+
void this.loadSessions();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
269
288
|
},
|
|
270
289
|
|
|
271
290
|
persistSessionFilterCache() {
|
|
@@ -412,7 +431,12 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
412
431
|
this.persistSessionPinnedMap();
|
|
413
432
|
},
|
|
414
433
|
|
|
415
|
-
async onSessionSourceChange() {
|
|
434
|
+
async onSessionSourceChange(event) {
|
|
435
|
+
const rawValue = event && event.target && typeof event.target.value === 'string'
|
|
436
|
+
? event.target.value
|
|
437
|
+
: this.sessionFilterSource;
|
|
438
|
+
const cached = buildSessionFilterCacheState(rawValue, this.sessionPathFilter);
|
|
439
|
+
this.sessionFilterSource = cached.source;
|
|
416
440
|
this.refreshSessionPathOptions(this.sessionFilterSource);
|
|
417
441
|
this.persistSessionFilterCache();
|
|
418
442
|
syncSessionsFilterUrl(this);
|
|
@@ -10,13 +10,15 @@ export function createSessionTrashMethods(options = {}) {
|
|
|
10
10
|
const deletedAt = typeof result.deletedAt === 'string' && result.deletedAt
|
|
11
11
|
? result.deletedAt
|
|
12
12
|
: new Date().toISOString();
|
|
13
|
-
const source = session && session.source === 'claude'
|
|
13
|
+
const source = session && (session.source === 'claude' || session.source === 'gemini')
|
|
14
|
+
? session.source
|
|
15
|
+
: 'codex';
|
|
14
16
|
return {
|
|
15
17
|
trashId: typeof result.trashId === 'string' ? result.trashId : '',
|
|
16
18
|
source,
|
|
17
19
|
sourceLabel: session && typeof session.sourceLabel === 'string' && session.sourceLabel
|
|
18
20
|
? session.sourceLabel
|
|
19
|
-
: (source === 'claude' ? 'Claude Code' : 'Codex'),
|
|
21
|
+
: (source === 'claude' ? 'Claude Code' : (source === 'gemini' ? 'Gemini CLI' : 'Codex')),
|
|
20
22
|
sessionId: session && typeof session.sessionId === 'string' ? session.sessionId : '',
|
|
21
23
|
title: session && typeof session.title === 'string' && session.title
|
|
22
24
|
? session.title
|
|
@@ -257,6 +257,8 @@ const DICT = Object.freeze({
|
|
|
257
257
|
'dashboard.message.none': '暂无提示',
|
|
258
258
|
'dashboard.sessionSource.codex': 'Codex',
|
|
259
259
|
'dashboard.sessionSource.claude': 'Claude Code',
|
|
260
|
+
'dashboard.sessionSource.gemini': 'Gemini CLI',
|
|
261
|
+
'dashboard.sessionSource.codebuddy': 'CodeBuddy Code',
|
|
260
262
|
'dashboard.sessionSource.all': '全部',
|
|
261
263
|
'dashboard.sessionPath.all': '全部路径',
|
|
262
264
|
'dashboard.sessionQuery.unsupported': '当前来源不支持',
|
|
@@ -502,7 +504,7 @@ const DICT = Object.freeze({
|
|
|
502
504
|
|
|
503
505
|
// Docs panel
|
|
504
506
|
'docs.title': 'CLI 安装文档',
|
|
505
|
-
'docs.subtitle': '查看 Claude Code / Codex CLI 命令。',
|
|
507
|
+
'docs.subtitle': '查看 Claude Code / Gemini CLI / CodeBuddy Code / Codex CLI 命令。',
|
|
506
508
|
'docs.section.commands': '安装命令',
|
|
507
509
|
'docs.section.commandsNote': '命令可直接复制。',
|
|
508
510
|
'docs.section.faq': '常见问题',
|
|
@@ -518,10 +520,10 @@ const DICT = Object.freeze({
|
|
|
518
520
|
'docs.rule.2': '自定义镜像仅用于安装与升级。'
|
|
519
521
|
,
|
|
520
522
|
'docs.tip.win.1': 'PowerShell 报权限不足(EACCES/EPERM)时,请以管理员身份执行安装命令。',
|
|
521
|
-
'docs.tip.win.2': '安装后若仍提示找不到命令,重开终端并执行:where codex / where claude。',
|
|
523
|
+
'docs.tip.win.2': '安装后若仍提示找不到命令,重开终端并执行:where codex / where claude / where gemini / where codebuddy。',
|
|
522
524
|
'docs.tip.win.3': '公司网络受限时,可先切换镜像源快捷项(npmmirror / 腾讯云 / 自定义)。',
|
|
523
525
|
'docs.tip.unix.1': '出现 EACCES 权限错误时,优先修复 Node 全局目录权限,不建议直接 sudo npm。',
|
|
524
|
-
'docs.tip.unix.2': '安装后若命令未生效,重开终端并执行:which codex / which claude。',
|
|
526
|
+
'docs.tip.unix.2': '安装后若命令未生效,重开终端并执行:which codex / which claude / which gemini / which codebuddy。',
|
|
525
527
|
'docs.tip.unix.3': '公司网络受限时,可先切换镜像源快捷项(npmmirror / 腾讯云 / 自定义)。'
|
|
526
528
|
,
|
|
527
529
|
|
|
@@ -533,10 +535,12 @@ const DICT = Object.freeze({
|
|
|
533
535
|
'sessions.allPaths': '全部路径',
|
|
534
536
|
'sessions.source.codex': 'Codex',
|
|
535
537
|
'sessions.source.claudeCode': 'Claude Code',
|
|
538
|
+
'sessions.source.gemini': 'Gemini CLI',
|
|
539
|
+
'sessions.source.codebuddy': 'CodeBuddy Code',
|
|
536
540
|
'sessions.loadingList': '会话加载中...',
|
|
537
541
|
'sessions.empty': '暂无可用会话记录',
|
|
538
542
|
'sessions.unknownTime': '未知时间',
|
|
539
|
-
'sessions.query.placeholder.enabled': '关键词检索(支持 Codex/Claude,例:claude code)',
|
|
543
|
+
'sessions.query.placeholder.enabled': '关键词检索(支持 Codex/Claude/Gemini/CodeBuddy,例:claude code)',
|
|
540
544
|
'sessions.query.placeholder.disabled': '当前来源暂不支持关键词检索',
|
|
541
545
|
'sessions.pin': '置顶',
|
|
542
546
|
'sessions.unpin': '取消置顶',
|
|
@@ -634,6 +638,10 @@ const DICT = Object.freeze({
|
|
|
634
638
|
'usage.summary.avgMessagesPerSession': '平均每会话消息',
|
|
635
639
|
'usage.summary.busiestDay': '最忙日',
|
|
636
640
|
'usage.summary.busiestHour': '高峰时段',
|
|
641
|
+
'usage.currentSession.title': '当前会话',
|
|
642
|
+
'usage.currentSession.apiDuration': 'API时长',
|
|
643
|
+
'usage.currentSession.totalDuration': '总时长',
|
|
644
|
+
'usage.currentSession.tokens': 'Token',
|
|
637
645
|
'usage.range.kicker.all': '全部',
|
|
638
646
|
'usage.range.kicker.30d': '近 30 天',
|
|
639
647
|
'usage.range.kicker.7d': '近 7 天',
|
|
@@ -1274,6 +1282,8 @@ const DICT = Object.freeze({
|
|
|
1274
1282
|
'dashboard.message.none': 'No messages',
|
|
1275
1283
|
'dashboard.sessionSource.codex': 'Codex',
|
|
1276
1284
|
'dashboard.sessionSource.claude': 'Claude Code',
|
|
1285
|
+
'dashboard.sessionSource.gemini': 'Gemini CLI',
|
|
1286
|
+
'dashboard.sessionSource.codebuddy': 'CodeBuddy Code',
|
|
1277
1287
|
'dashboard.sessionSource.all': 'All',
|
|
1278
1288
|
'dashboard.sessionPath.all': 'All paths',
|
|
1279
1289
|
'dashboard.sessionQuery.unsupported': 'Unsupported source',
|
|
@@ -1519,7 +1529,7 @@ const DICT = Object.freeze({
|
|
|
1519
1529
|
|
|
1520
1530
|
// Docs panel
|
|
1521
1531
|
'docs.title': 'CLI Install',
|
|
1522
|
-
'docs.subtitle': 'Install commands for Claude Code / Codex CLI.',
|
|
1532
|
+
'docs.subtitle': 'Install commands for Claude Code / Gemini CLI / CodeBuddy Code / Codex CLI.',
|
|
1523
1533
|
'docs.section.commands': 'Commands',
|
|
1524
1534
|
'docs.section.commandsNote': 'Copy and run directly.',
|
|
1525
1535
|
'docs.section.faq': 'FAQ',
|
|
@@ -1535,10 +1545,10 @@ const DICT = Object.freeze({
|
|
|
1535
1545
|
'docs.rule.2': 'Custom registry is used for install/update only.'
|
|
1536
1546
|
,
|
|
1537
1547
|
'docs.tip.win.1': 'If PowerShell reports permission errors (EACCES/EPERM), run the install command as Administrator.',
|
|
1538
|
-
'docs.tip.win.2': 'If the command is still not found after install, reopen the terminal and run: where codex / where claude.',
|
|
1548
|
+
'docs.tip.win.2': 'If the command is still not found after install, reopen the terminal and run: where codex / where claude / where gemini / where codebuddy.',
|
|
1539
1549
|
'docs.tip.win.3': 'If your network blocks npm, try switching registry presets (npmmirror / Tencent / Custom).',
|
|
1540
1550
|
'docs.tip.unix.1': 'If you hit EACCES, fix your global Node directory permissions instead of using sudo npm.',
|
|
1541
|
-
'docs.tip.unix.2': 'If the command is not available after install, reopen the terminal and run: which codex / which claude.',
|
|
1551
|
+
'docs.tip.unix.2': 'If the command is not available after install, reopen the terminal and run: which codex / which claude / which gemini / which codebuddy.',
|
|
1542
1552
|
'docs.tip.unix.3': 'If your network blocks npm, try switching registry presets (npmmirror / Tencent / Custom).'
|
|
1543
1553
|
,
|
|
1544
1554
|
|
|
@@ -1550,10 +1560,12 @@ const DICT = Object.freeze({
|
|
|
1550
1560
|
'sessions.allPaths': 'All paths',
|
|
1551
1561
|
'sessions.source.codex': 'Codex',
|
|
1552
1562
|
'sessions.source.claudeCode': 'Claude Code',
|
|
1563
|
+
'sessions.source.gemini': 'Gemini CLI',
|
|
1564
|
+
'sessions.source.codebuddy': 'CodeBuddy Code',
|
|
1553
1565
|
'sessions.loadingList': 'Loading sessions...',
|
|
1554
1566
|
'sessions.empty': 'No sessions found',
|
|
1555
1567
|
'sessions.unknownTime': 'unknown time',
|
|
1556
|
-
'sessions.query.placeholder.enabled': 'Search keywords (Codex/Claude, e.g. claude code)',
|
|
1568
|
+
'sessions.query.placeholder.enabled': 'Search keywords (Codex/Claude/Gemini/CodeBuddy, e.g. claude code)',
|
|
1557
1569
|
'sessions.query.placeholder.disabled': 'Keyword search is not available for this source',
|
|
1558
1570
|
'sessions.pin': 'Pin',
|
|
1559
1571
|
'sessions.unpin': 'Unpin',
|
|
@@ -1651,6 +1663,10 @@ const DICT = Object.freeze({
|
|
|
1651
1663
|
'usage.summary.avgMessagesPerSession': 'Avg messages/session',
|
|
1652
1664
|
'usage.summary.busiestDay': 'Busiest day',
|
|
1653
1665
|
'usage.summary.busiestHour': 'Peak hour',
|
|
1666
|
+
'usage.currentSession.title': 'Current session',
|
|
1667
|
+
'usage.currentSession.apiDuration': 'API duration',
|
|
1668
|
+
'usage.currentSession.totalDuration': 'Total duration',
|
|
1669
|
+
'usage.currentSession.tokens': 'Tokens',
|
|
1654
1670
|
'usage.range.kicker.all': 'All',
|
|
1655
1671
|
'usage.range.kicker.30d': 'Last 30 days',
|
|
1656
1672
|
'usage.range.kicker.7d': 'Last 7 days',
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
<div class="side-item-title">{{ t('side.sessions.browser') }}</div>
|
|
215
215
|
<div class="side-item-meta">
|
|
216
216
|
<span>{{ t('side.sessions.browser.meta') }}</span>
|
|
217
|
-
<span>{{ t('sessions.sourceLabel', { value: (sessionFilterSource === 'all' ? t('sessions.source.all') : (sessionFilterSource === '
|
|
217
|
+
<span>{{ t('sessions.sourceLabel', { value: (sessionFilterSource === 'all' ? t('sessions.source.all') : (sessionFilterSource === 'claude' ? 'Claude Code' : (sessionFilterSource === 'gemini' ? 'Gemini CLI' : (sessionFilterSource === 'codebuddy' ? 'CodeBuddy Code' : 'Codex')))) }) }}</span>
|
|
218
218
|
</div>
|
|
219
219
|
</button>
|
|
220
220
|
<button
|
|
@@ -369,7 +369,17 @@
|
|
|
369
369
|
<div class="status-chip">
|
|
370
370
|
<span class="label">{{ t('status.currentSource') }}</span>
|
|
371
371
|
<span class="value">
|
|
372
|
-
{{ sessionFilterSource === 'all'
|
|
372
|
+
{{ sessionFilterSource === 'all'
|
|
373
|
+
? t('sessions.source.all')
|
|
374
|
+
: (sessionFilterSource === 'codex'
|
|
375
|
+
? t('sessions.source.codex')
|
|
376
|
+
: (sessionFilterSource === 'claude'
|
|
377
|
+
? t('sessions.source.claudeCode')
|
|
378
|
+
: (sessionFilterSource === 'gemini'
|
|
379
|
+
? t('sessions.source.gemini')
|
|
380
|
+
: (sessionFilterSource === 'codebuddy'
|
|
381
|
+
? t('sessions.source.codebuddy')
|
|
382
|
+
: t('sessions.source.codex'))))) }}
|
|
373
383
|
</span>
|
|
374
384
|
</div>
|
|
375
385
|
<div class="status-chip">
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
<div class="selector-section">
|
|
25
25
|
<div class="selector-header">
|
|
26
26
|
<span class="selector-title">{{ t('sessions.sourceTitle') }}</span>
|
|
27
|
-
<div class="selector-actions">
|
|
27
|
+
<div class="selector-actions sessions-header-actions">
|
|
28
28
|
<button class="btn-tool btn-tool-compact" @click="loadSessions({ forceRefresh: true })" :disabled="sessionsLoading">
|
|
29
29
|
{{ sessionsLoading ? t('sessions.refreshing') : t('sessions.refresh') }}
|
|
30
30
|
</button>
|
|
@@ -35,10 +35,12 @@
|
|
|
35
35
|
</div>
|
|
36
36
|
<div class="session-toolbar">
|
|
37
37
|
<div class="session-toolbar-group session-toolbar-primary">
|
|
38
|
-
<select class="session-source-select" v-model="sessionFilterSource" @change="onSessionSourceChange" :disabled="sessionsLoading">
|
|
38
|
+
<select class="session-source-select" v-model="sessionFilterSource" @change="onSessionSourceChange($event)" :disabled="sessionsLoading">
|
|
39
39
|
<option value="all">{{ t('common.all') }}</option>
|
|
40
40
|
<option value="codex">{{ t('sessions.source.codex') }}</option>
|
|
41
41
|
<option value="claude">{{ t('sessions.source.claudeCode') }}</option>
|
|
42
|
+
<option value="gemini">{{ t('sessions.source.gemini') }}</option>
|
|
43
|
+
<option value="codebuddy">{{ t('sessions.source.codebuddy') }}</option>
|
|
42
44
|
</select>
|
|
43
45
|
<select
|
|
44
46
|
class="session-path-select"
|
|
@@ -42,6 +42,13 @@
|
|
|
42
42
|
{{ t('usage.refreshOverlay') }}
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
|
+
<div v-if="usageCurrentSessionStats" class="usage-current-session-bar">
|
|
46
|
+
<span class="usage-current-session-label">{{ usageCurrentSessionStats.label }}</span>
|
|
47
|
+
<span class="usage-current-session-item">{{ usageCurrentSessionStats.apiDurationText }} <strong>{{ usageCurrentSessionStats.apiDurationLabel }}</strong></span>
|
|
48
|
+
<span class="usage-current-session-item">{{ usageCurrentSessionStats.totalDurationText }} <strong>{{ usageCurrentSessionStats.totalDurationLabel }}</strong></span>
|
|
49
|
+
<span class="usage-current-session-item">{{ usageCurrentSessionStats.tokenText }} <strong>{{ usageCurrentSessionStats.tokenLabel }}</strong></span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
45
52
|
<div class="usage-summary-grid">
|
|
46
53
|
<div
|
|
47
54
|
v-for="card in sessionUsageSummaryCards"
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
display: flex;
|
|
19
19
|
justify-content: space-between;
|
|
20
20
|
align-items: center;
|
|
21
|
+
flex-wrap: nowrap;
|
|
22
|
+
gap: 10px;
|
|
21
23
|
margin-bottom: 2px;
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -81,12 +83,57 @@
|
|
|
81
83
|
text-transform: none;
|
|
82
84
|
letter-spacing: 0.03em;
|
|
83
85
|
opacity: 0.85;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
overflow: hidden;
|
|
88
|
+
text-overflow: ellipsis;
|
|
89
|
+
white-space: nowrap;
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
.selector-actions {
|
|
87
|
-
display:
|
|
88
|
-
|
|
93
|
+
display: inline-grid;
|
|
94
|
+
grid-auto-flow: column;
|
|
95
|
+
grid-auto-columns: max-content;
|
|
96
|
+
column-gap: var(--spacing-xs);
|
|
89
97
|
align-items: center;
|
|
98
|
+
justify-content: end;
|
|
99
|
+
white-space: nowrap;
|
|
100
|
+
flex: 0 0 auto;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.selector-actions > .btn-tool,
|
|
104
|
+
.selector-actions > .btn-tool-compact {
|
|
105
|
+
flex: 0 0 auto;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.sessions-header-actions {
|
|
109
|
+
display: flex !important;
|
|
110
|
+
flex-direction: row !important;
|
|
111
|
+
flex-wrap: nowrap !important;
|
|
112
|
+
align-items: center !important;
|
|
113
|
+
gap: 8px !important;
|
|
114
|
+
white-space: nowrap;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.sessions-header-actions > .btn-tool,
|
|
118
|
+
.sessions-header-actions > .btn-tool-compact {
|
|
119
|
+
display: inline-flex !important;
|
|
120
|
+
width: auto !important;
|
|
121
|
+
margin: 0 !important;
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
flex: 0 0 auto;
|
|
124
|
+
height: 28px !important;
|
|
125
|
+
min-height: 28px !important;
|
|
126
|
+
padding: 0 10px !important;
|
|
127
|
+
line-height: 1 !important;
|
|
128
|
+
border-radius: 8px !important;
|
|
129
|
+
border: 1px solid var(--color-border-soft) !important;
|
|
130
|
+
background: rgba(255, 255, 255, 0.72) !important;
|
|
131
|
+
font-size: 12px !important;
|
|
132
|
+
font-weight: var(--font-weight-secondary) !important;
|
|
133
|
+
color: var(--color-text-secondary) !important;
|
|
134
|
+
box-shadow: none !important;
|
|
135
|
+
letter-spacing: -0.01em !important;
|
|
136
|
+
justify-content: center !important;
|
|
90
137
|
}
|
|
91
138
|
|
|
92
139
|
.health-report {
|
|
@@ -280,11 +280,9 @@
|
|
|
280
280
|
font-weight: var(--font-weight-secondary);
|
|
281
281
|
color: var(--color-text-primary);
|
|
282
282
|
line-height: 1.4;
|
|
283
|
-
|
|
284
|
-
-webkit-line-clamp: 2;
|
|
285
|
-
-webkit-box-orient: vertical;
|
|
286
|
-
white-space: normal;
|
|
283
|
+
white-space: nowrap;
|
|
287
284
|
overflow: hidden;
|
|
285
|
+
text-overflow: ellipsis;
|
|
288
286
|
flex: 1;
|
|
289
287
|
max-width: none;
|
|
290
288
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
display: grid;
|
|
3
3
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
4
4
|
gap: var(--spacing-xs);
|
|
5
|
-
margin-bottom: var(--spacing-
|
|
5
|
+
margin-bottom: var(--spacing-xs);
|
|
6
6
|
align-items: end;
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
align-items: center;
|
|
32
32
|
justify-content: flex-end;
|
|
33
33
|
gap: var(--spacing-xs);
|
|
34
|
-
margin-top: -
|
|
35
|
-
padding-top:
|
|
36
|
-
margin-bottom:
|
|
34
|
+
margin-top: -1px;
|
|
35
|
+
padding-top: 4px;
|
|
36
|
+
margin-bottom: var(--spacing-xs);
|
|
37
37
|
border-top: 1px dashed var(--color-border-soft);
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -44,6 +44,30 @@
|
|
|
44
44
|
margin-bottom: 16px;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
.usage-current-session-bar {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: 12px;
|
|
52
|
+
padding: 10px 12px;
|
|
53
|
+
margin: 0 0 14px;
|
|
54
|
+
border-radius: 12px;
|
|
55
|
+
border: 1px solid var(--color-border-soft);
|
|
56
|
+
background: var(--color-surface-alt);
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
color: var(--color-text-secondary);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.usage-current-session-label {
|
|
62
|
+
font-weight: 700;
|
|
63
|
+
color: var(--color-text-primary);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.usage-current-session-item strong {
|
|
67
|
+
font-weight: 700;
|
|
68
|
+
color: var(--color-text-primary);
|
|
69
|
+
}
|
|
70
|
+
|
|
47
71
|
.usage-range-group {
|
|
48
72
|
display: flex;
|
|
49
73
|
gap: 8px;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|