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.
- package/README.md +289 -152
- package/README.zh.md +321 -0
- package/cli/agents-files.js +224 -0
- package/cli/archive-helpers.js +446 -0
- package/cli/auth-profiles.js +359 -0
- package/cli/builtin-proxy.js +1044 -0
- package/cli/claude-proxy.js +998 -0
- package/cli/config-bootstrap.js +384 -0
- package/cli/openai-bridge.js +950 -0
- package/cli/openclaw-config.js +629 -0
- package/cli/session-usage.concurrent.js +28 -0
- package/cli/session-usage.js +112 -0
- package/cli/session-usage.models.js +176 -0
- package/cli/skills.js +1141 -0
- package/cli/zip-commands.js +510 -0
- package/cli.js +9408 -9719
- package/lib/cli-models-utils.js +109 -1
- package/lib/cli-path-utils.js +69 -0
- package/lib/cli-sessions.js +386 -0
- package/lib/download-artifacts.js +77 -0
- package/lib/task-orchestrator.js +869 -0
- package/package.json +14 -10
- package/res/logo.png +0 -0
- package/res/vue.global.prod.js +13 -0
- package/web-ui/app.js +193 -15
- package/web-ui/index.html +5 -1
- package/web-ui/logic.agents-diff.mjs +1 -1
- package/web-ui/logic.claude.mjs +60 -0
- package/web-ui/logic.runtime.mjs +11 -7
- package/web-ui/logic.sessions.mjs +372 -21
- package/web-ui/modules/api.mjs +22 -1
- package/web-ui/modules/app.computed.dashboard.mjs +23 -10
- package/web-ui/modules/app.computed.index.mjs +4 -0
- package/web-ui/modules/app.computed.main-tabs.mjs +198 -0
- package/web-ui/modules/app.computed.session.mjs +521 -9
- package/web-ui/modules/app.methods.agents.mjs +62 -11
- package/web-ui/modules/app.methods.codex-config.mjs +189 -34
- package/web-ui/modules/app.methods.index.mjs +7 -1
- package/web-ui/modules/app.methods.install.mjs +24 -20
- package/web-ui/modules/app.methods.navigation.mjs +142 -1
- package/web-ui/modules/app.methods.openclaw-core.mjs +339 -39
- package/web-ui/modules/app.methods.openclaw-editing.mjs +39 -4
- package/web-ui/modules/app.methods.openclaw-persist.mjs +122 -4
- package/web-ui/modules/app.methods.providers.mjs +192 -53
- package/web-ui/modules/app.methods.session-actions.mjs +99 -19
- package/web-ui/modules/app.methods.session-browser.mjs +196 -5
- package/web-ui/modules/app.methods.session-timeline.mjs +22 -15
- package/web-ui/modules/app.methods.session-trash.mjs +3 -0
- package/web-ui/modules/app.methods.startup-claude.mjs +70 -71
- package/web-ui/modules/app.methods.task-orchestration.mjs +471 -0
- package/web-ui/modules/config-mode.computed.mjs +2 -0
- package/web-ui/modules/config-template-confirm-pref.mjs +33 -0
- package/web-ui/modules/i18n.mjs +1609 -0
- package/web-ui/modules/plugins.computed.mjs +220 -0
- package/web-ui/modules/plugins.methods.mjs +620 -0
- package/web-ui/modules/plugins.storage.mjs +37 -0
- package/web-ui/partials/index/layout-footer.html +1 -57
- package/web-ui/partials/index/layout-header.html +299 -175
- package/web-ui/partials/index/modal-config-template-agents.html +79 -29
- package/web-ui/partials/index/modal-confirm-toast.html +1 -1
- package/web-ui/partials/index/modal-health-check.html +14 -14
- package/web-ui/partials/index/modal-openclaw-config.html +47 -42
- package/web-ui/partials/index/modal-skills.html +130 -114
- package/web-ui/partials/index/modals-basic.html +71 -102
- package/web-ui/partials/index/panel-config-claude.html +50 -12
- package/web-ui/partials/index/panel-config-codex.html +34 -37
- package/web-ui/partials/index/panel-config-openclaw.html +10 -16
- package/web-ui/partials/index/panel-docs.html +147 -0
- package/web-ui/partials/index/panel-market.html +38 -38
- package/web-ui/partials/index/panel-orchestration.html +397 -0
- package/web-ui/partials/index/panel-plugins.html +243 -0
- package/web-ui/partials/index/panel-sessions.html +51 -146
- package/web-ui/partials/index/panel-settings.html +188 -96
- package/web-ui/partials/index/panel-usage.html +353 -0
- package/web-ui/session-helpers.mjs +221 -10
- package/web-ui/styles/base-theme.css +120 -229
- package/web-ui/styles/controls-forms.css +59 -51
- package/web-ui/styles/docs-panel.css +247 -0
- package/web-ui/styles/layout-shell.css +394 -128
- package/web-ui/styles/modals-core.css +18 -3
- package/web-ui/styles/navigation-panels.css +184 -183
- package/web-ui/styles/plugins-panel.css +518 -0
- package/web-ui/styles/responsive.css +102 -62
- package/web-ui/styles/sessions-list.css +13 -27
- package/web-ui/styles/sessions-preview.css +13 -7
- package/web-ui/styles/sessions-toolbar-trash.css +25 -0
- package/web-ui/styles/sessions-usage.css +581 -6
- package/web-ui/styles/settings-panel.css +166 -0
- package/web-ui/styles/skills-list.css +16 -11
- package/web-ui/styles/skills-market.css +63 -2
- package/web-ui/styles/task-orchestration.css +776 -0
- package/web-ui/styles/titles-cards.css +67 -66
- package/web-ui/styles.css +4 -0
- package/README.en.md +0 -259
- package/res/screenshot.png +0 -0
- package/res/vue.global.js +0 -18552
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeConfigTemplateDiffConfirmEnabled,
|
|
3
|
+
persistConfigTemplateDiffConfirmEnabledToStorage
|
|
4
|
+
} from './config-template-confirm-pref.mjs';
|
|
5
|
+
|
|
1
6
|
export function createSessionActionMethods(options = {}) {
|
|
2
7
|
const {
|
|
3
8
|
api,
|
|
@@ -153,6 +158,54 @@ export function createSessionActionMethods(options = {}) {
|
|
|
153
158
|
return this.quoteShellArg(value);
|
|
154
159
|
},
|
|
155
160
|
|
|
161
|
+
normalizeShareCommandPrefix(value) {
|
|
162
|
+
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
163
|
+
if (normalized === 'codexmate') {
|
|
164
|
+
return 'codexmate';
|
|
165
|
+
}
|
|
166
|
+
return 'npm start';
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
normalizeSessionTrashEnabled(value) {
|
|
170
|
+
if (value === false) return false;
|
|
171
|
+
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
172
|
+
if (normalized === '0' || normalized === 'false' || normalized === 'off' || normalized === 'no') {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
normalizeConfigTemplateDiffConfirmEnabled(value) {
|
|
179
|
+
return normalizeConfigTemplateDiffConfirmEnabled(value);
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
setSessionTrashEnabled(value) {
|
|
183
|
+
const enabled = this.normalizeSessionTrashEnabled(value);
|
|
184
|
+
this.sessionTrashEnabled = enabled;
|
|
185
|
+
try {
|
|
186
|
+
localStorage.setItem('codexmateSessionTrashEnabled', enabled ? 'true' : 'false');
|
|
187
|
+
} catch (_) {}
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
setConfigTemplateDiffConfirmEnabled(value) {
|
|
191
|
+
const enabled = this.normalizeConfigTemplateDiffConfirmEnabled(value);
|
|
192
|
+
this.configTemplateDiffConfirmEnabled = enabled;
|
|
193
|
+
persistConfigTemplateDiffConfirmEnabledToStorage(enabled);
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
getShareCommandPrefixInvocation() {
|
|
197
|
+
const prefix = this.normalizeShareCommandPrefix(this.shareCommandPrefix);
|
|
198
|
+
return prefix === 'codexmate' ? 'codexmate' : 'npm start';
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
setShareCommandPrefix(value) {
|
|
202
|
+
const normalized = this.normalizeShareCommandPrefix(value);
|
|
203
|
+
this.shareCommandPrefix = normalized;
|
|
204
|
+
try {
|
|
205
|
+
localStorage.setItem('codexmateShareCommandPrefix', normalized);
|
|
206
|
+
} catch (_) {}
|
|
207
|
+
},
|
|
208
|
+
|
|
156
209
|
fallbackCopyText(text) {
|
|
157
210
|
let textarea = null;
|
|
158
211
|
try {
|
|
@@ -256,16 +309,19 @@ export function createSessionActionMethods(options = {}) {
|
|
|
256
309
|
const baseUrl = typeof payload.baseUrl === 'string' ? payload.baseUrl.trim() : '';
|
|
257
310
|
const apiKey = typeof payload.apiKey === 'string' ? payload.apiKey : '';
|
|
258
311
|
const model = typeof payload.model === 'string' ? payload.model.trim() : '';
|
|
312
|
+
const bridge = typeof payload.bridge === 'string' ? payload.bridge.trim() : '';
|
|
259
313
|
if (!name || !baseUrl) return '';
|
|
260
314
|
|
|
315
|
+
const cli = this.getShareCommandPrefixInvocation();
|
|
261
316
|
const nameArg = this.quoteShellArg(name);
|
|
262
317
|
const urlArg = this.quoteShellArg(baseUrl);
|
|
263
318
|
const keyArg = apiKey ? this.quoteShellArg(apiKey) : '';
|
|
264
|
-
const switchCmd =
|
|
319
|
+
const switchCmd = `${cli} switch ${nameArg}`;
|
|
320
|
+
const bridgeArgs = bridge ? ` --bridge ${this.quoteShellArg(bridge)}` : '';
|
|
265
321
|
const addCmd = apiKey
|
|
266
|
-
?
|
|
267
|
-
:
|
|
268
|
-
const modelCmd = model ? ` &&
|
|
322
|
+
? `${cli} add ${nameArg} ${urlArg} ${keyArg}${bridgeArgs}`
|
|
323
|
+
: `${cli} add ${nameArg} ${urlArg}${bridgeArgs}`;
|
|
324
|
+
const modelCmd = model ? ` && ${cli} use ${this.quoteShellArg(model)}` : '';
|
|
269
325
|
return `${addCmd} && ${switchCmd}${modelCmd}`;
|
|
270
326
|
},
|
|
271
327
|
|
|
@@ -280,7 +336,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
280
336
|
const urlArg = this.quoteShellArg(baseUrl);
|
|
281
337
|
const keyArg = this.quoteShellArg(apiKey);
|
|
282
338
|
const modelArg = this.quoteShellArg(model);
|
|
283
|
-
return
|
|
339
|
+
return `${this.getShareCommandPrefixInvocation()} claude ${urlArg} ${keyArg} ${modelArg}`;
|
|
284
340
|
},
|
|
285
341
|
|
|
286
342
|
async copyProviderShareCommand(provider) {
|
|
@@ -290,7 +346,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
290
346
|
return;
|
|
291
347
|
}
|
|
292
348
|
if (!this.shouldAllowProviderShare(provider)) {
|
|
293
|
-
this.showMessage('
|
|
349
|
+
this.showMessage('不可分享', 'info');
|
|
294
350
|
return;
|
|
295
351
|
}
|
|
296
352
|
if (this.providerShareLoading[name]) {
|
|
@@ -389,6 +445,9 @@ export function createSessionActionMethods(options = {}) {
|
|
|
389
445
|
}
|
|
390
446
|
|
|
391
447
|
this.showMessage('操作成功', 'success');
|
|
448
|
+
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
449
|
+
this.invalidateSessionsUsageData({ preserveList: true });
|
|
450
|
+
}
|
|
392
451
|
try {
|
|
393
452
|
await this.loadSessions();
|
|
394
453
|
if (res.sessionId) {
|
|
@@ -412,13 +471,27 @@ export function createSessionActionMethods(options = {}) {
|
|
|
412
471
|
this.showMessage('不支持此操作', 'error');
|
|
413
472
|
return;
|
|
414
473
|
}
|
|
474
|
+
const useTrash = this.sessionTrashEnabled !== false;
|
|
475
|
+
if (!useTrash && typeof this.requestConfirmDialog === 'function') {
|
|
476
|
+
const confirmed = await this.requestConfirmDialog({
|
|
477
|
+
title: '直接删除会话',
|
|
478
|
+
message: '关闭回收站后,删除会话将直接永久删除,且无法恢复。',
|
|
479
|
+
confirmText: '直接删除',
|
|
480
|
+
cancelText: '取消',
|
|
481
|
+
danger: true
|
|
482
|
+
});
|
|
483
|
+
if (!confirmed) {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
415
487
|
const key = this.getSessionExportKey(session);
|
|
416
488
|
if (this.sessionDeleting[key]) {
|
|
417
489
|
return;
|
|
418
490
|
}
|
|
419
491
|
this.sessionDeleting[key] = true;
|
|
420
492
|
try {
|
|
421
|
-
const
|
|
493
|
+
const action = useTrash ? 'trash-session' : 'delete-session';
|
|
494
|
+
const res = await api(action, {
|
|
422
495
|
source: session.source,
|
|
423
496
|
sessionId: session.sessionId,
|
|
424
497
|
filePath: session.filePath
|
|
@@ -428,19 +501,26 @@ export function createSessionActionMethods(options = {}) {
|
|
|
428
501
|
return;
|
|
429
502
|
}
|
|
430
503
|
this.removeSessionPin(session);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
504
|
+
if (useTrash) {
|
|
505
|
+
this.invalidateSessionTrashRequests();
|
|
506
|
+
this.showMessage('已移入回收站', 'success');
|
|
507
|
+
if (this.sessionTrashLoadedOnce) {
|
|
508
|
+
this.prependSessionTrashItem(this.buildSessionTrashItemFromSession(session, res), {
|
|
509
|
+
totalCount: res && res.totalCount !== undefined ? res.totalCount : undefined
|
|
510
|
+
});
|
|
511
|
+
} else {
|
|
512
|
+
this.sessionTrashTotalCount = this.normalizeSessionTrashTotalCount(
|
|
513
|
+
res && res.totalCount !== undefined
|
|
514
|
+
? res.totalCount
|
|
515
|
+
: (this.normalizeSessionTrashTotalCount(this.sessionTrashTotalCount, this.sessionTrashItems) + 1),
|
|
516
|
+
this.sessionTrashItems
|
|
517
|
+
);
|
|
518
|
+
}
|
|
437
519
|
} else {
|
|
438
|
-
this.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
this.sessionTrashItems
|
|
443
|
-
);
|
|
520
|
+
this.showMessage('已删除', 'success');
|
|
521
|
+
}
|
|
522
|
+
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
523
|
+
this.invalidateSessionsUsageData({ preserveList: true });
|
|
444
524
|
}
|
|
445
525
|
try {
|
|
446
526
|
await this.removeSessionFromCurrentList(session);
|
|
@@ -5,6 +5,69 @@ import {
|
|
|
5
5
|
normalizeSessionPathFilter
|
|
6
6
|
} from '../logic.mjs';
|
|
7
7
|
|
|
8
|
+
function isSessionLoadNativeDialogEnabled(vm) {
|
|
9
|
+
if (vm && typeof vm.isSessionLoadNativeDialogEnabled === 'function' && vm.isSessionLoadNativeDialogEnabled !== isSessionLoadNativeDialogEnabled) {
|
|
10
|
+
try {
|
|
11
|
+
return !!vm.isSessionLoadNativeDialogEnabled();
|
|
12
|
+
} catch (_) {
|
|
13
|
+
// fall through to shared detection
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
if (globalThis && globalThis.__CODEXMATE_SESSION_LOAD_NATIVE_DIALOG__ === true) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
} catch (_) {
|
|
22
|
+
// ignore global flag lookup failures
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
if (typeof localStorage !== 'undefined' && typeof localStorage.getItem === 'function') {
|
|
27
|
+
const stored = String(localStorage.getItem('codexmateSessionLoadNativeDialog') || '').trim().toLowerCase();
|
|
28
|
+
if (stored === '1' || stored === 'true' || stored === 'yes' || stored === 'on') {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} catch (_) {
|
|
33
|
+
// ignore storage lookup failures
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const search = typeof location !== 'undefined' && location && typeof location.search === 'string'
|
|
38
|
+
? location.search
|
|
39
|
+
: (typeof window !== 'undefined' && window.location && typeof window.location.search === 'string'
|
|
40
|
+
? window.location.search
|
|
41
|
+
: '');
|
|
42
|
+
if (!search) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const params = new URLSearchParams(search);
|
|
46
|
+
const value = String(params.get('sessionLoadNativeDialog') || '').trim().toLowerCase();
|
|
47
|
+
return value === '1' || value === 'true' || value === 'yes' || value === 'on';
|
|
48
|
+
} catch (_) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function emitSessionLoadNativeDialog(vm, step, details = '') {
|
|
54
|
+
if (!isSessionLoadNativeDialogEnabled(vm)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const alertFn = typeof globalThis.alert === 'function'
|
|
58
|
+
? globalThis.alert.bind(globalThis)
|
|
59
|
+
: (typeof window !== 'undefined' && typeof window.alert === 'function'
|
|
60
|
+
? window.alert.bind(window)
|
|
61
|
+
: null);
|
|
62
|
+
if (!alertFn) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const message = details
|
|
66
|
+
? `[codexmate][session-load] ${step}\n${details}`
|
|
67
|
+
: `[codexmate][session-load] ${step}`;
|
|
68
|
+
alertFn(message);
|
|
69
|
+
}
|
|
70
|
+
|
|
8
71
|
export function createSessionBrowserMethods(options = {}) {
|
|
9
72
|
const {
|
|
10
73
|
api,
|
|
@@ -84,11 +147,20 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
84
147
|
}
|
|
85
148
|
},
|
|
86
149
|
|
|
150
|
+
isSessionLoadNativeDialogEnabled() {
|
|
151
|
+
return isSessionLoadNativeDialogEnabled(this);
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
emitSessionLoadNativeDialog(step, details = '') {
|
|
155
|
+
emitSessionLoadNativeDialog(this, step, details);
|
|
156
|
+
},
|
|
157
|
+
|
|
87
158
|
async loadSessionPathOptions(options = {}) {
|
|
88
159
|
const source = options.source === 'claude' ? 'claude' : (options.source === 'all' ? 'all' : 'codex');
|
|
89
160
|
const forceRefresh = !!options.forceRefresh;
|
|
90
161
|
const loaded = !!this.sessionPathOptionsLoadedMap[source];
|
|
91
162
|
if (!forceRefresh && loaded) {
|
|
163
|
+
emitSessionLoadNativeDialog(this, 'loadSessionPathOptions:cache-hit', `source=${source}`);
|
|
92
164
|
if (source === this.sessionFilterSource) {
|
|
93
165
|
this.sessionPathOptionsLoading = false;
|
|
94
166
|
}
|
|
@@ -101,6 +173,11 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
101
173
|
const requestSeq = (Number(nextSeqMap[source]) || 0) + 1;
|
|
102
174
|
nextSeqMap[source] = requestSeq;
|
|
103
175
|
this.sessionPathRequestSeqMap = nextSeqMap;
|
|
176
|
+
emitSessionLoadNativeDialog(
|
|
177
|
+
this,
|
|
178
|
+
'loadSessionPathOptions:start',
|
|
179
|
+
`source=${source}\nforceRefresh=${forceRefresh}\nrequestSeq=${requestSeq}`
|
|
180
|
+
);
|
|
104
181
|
if (source === this.sessionFilterSource) {
|
|
105
182
|
this.sessionPathOptionsLoading = true;
|
|
106
183
|
}
|
|
@@ -111,6 +188,11 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
111
188
|
forceRefresh
|
|
112
189
|
});
|
|
113
190
|
if (requestSeq !== Number(((this.sessionPathRequestSeqMap || {})[source]) || 0)) {
|
|
191
|
+
emitSessionLoadNativeDialog(
|
|
192
|
+
this,
|
|
193
|
+
'loadSessionPathOptions:stale-response',
|
|
194
|
+
`source=${source}\nrequestSeq=${requestSeq}`
|
|
195
|
+
);
|
|
114
196
|
return;
|
|
115
197
|
}
|
|
116
198
|
if (res && !res.error && Array.isArray(res.paths)) {
|
|
@@ -119,8 +201,24 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
119
201
|
...this.sessionPathOptionsLoadedMap,
|
|
120
202
|
[source]: true
|
|
121
203
|
};
|
|
204
|
+
emitSessionLoadNativeDialog(
|
|
205
|
+
this,
|
|
206
|
+
'loadSessionPathOptions:success',
|
|
207
|
+
`source=${source}\npaths=${res.paths.length}`
|
|
208
|
+
);
|
|
209
|
+
} else if (res && res.error) {
|
|
210
|
+
emitSessionLoadNativeDialog(
|
|
211
|
+
this,
|
|
212
|
+
'loadSessionPathOptions:error',
|
|
213
|
+
`source=${source}\nerror=${res.error}`
|
|
214
|
+
);
|
|
122
215
|
}
|
|
123
|
-
} catch (
|
|
216
|
+
} catch (error) {
|
|
217
|
+
emitSessionLoadNativeDialog(
|
|
218
|
+
this,
|
|
219
|
+
'loadSessionPathOptions:exception',
|
|
220
|
+
`source=${source}\nerror=${error && error.message ? error.message : String(error)}`
|
|
221
|
+
);
|
|
124
222
|
// 路径补全失败不影响会话主流程
|
|
125
223
|
} finally {
|
|
126
224
|
if (
|
|
@@ -129,6 +227,11 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
129
227
|
) {
|
|
130
228
|
this.sessionPathOptionsLoading = false;
|
|
131
229
|
}
|
|
230
|
+
emitSessionLoadNativeDialog(
|
|
231
|
+
this,
|
|
232
|
+
'loadSessionPathOptions:complete',
|
|
233
|
+
`source=${source}\nrequestSeq=${requestSeq}`
|
|
234
|
+
);
|
|
132
235
|
}
|
|
133
236
|
},
|
|
134
237
|
|
|
@@ -359,16 +462,94 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
359
462
|
}
|
|
360
463
|
},
|
|
361
464
|
|
|
362
|
-
|
|
363
|
-
|
|
465
|
+
invalidateSessionsUsageData(options = {}) {
|
|
466
|
+
this.sessionsUsageLoadedOnce = false;
|
|
467
|
+
this.sessionsUsageError = '';
|
|
468
|
+
if (options.preserveList !== true) {
|
|
469
|
+
this.sessionsUsageList = [];
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
|
|
473
|
+
async loadSessionsUsage(options = {}) {
|
|
474
|
+
if (this.sessionsUsageLoading) return;
|
|
475
|
+
this.sessionsUsageLoading = true;
|
|
476
|
+
this.sessionsUsageError = '';
|
|
477
|
+
let loadSucceeded = false;
|
|
478
|
+
try {
|
|
479
|
+
const res = await api('list-sessions-usage', {
|
|
480
|
+
source: 'all',
|
|
481
|
+
limit: 2000,
|
|
482
|
+
forceRefresh: !!options.forceRefresh
|
|
483
|
+
});
|
|
484
|
+
if (res.error) {
|
|
485
|
+
this.sessionsUsageError = res.error;
|
|
486
|
+
this.showMessage(res.error, 'error');
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
this.sessionsUsageList = Array.isArray(res.sessions) ? res.sessions : [];
|
|
490
|
+
loadSucceeded = true;
|
|
491
|
+
} catch (e) {
|
|
492
|
+
this.sessionsUsageError = '加载 usage 统计失败';
|
|
493
|
+
this.showMessage('加载 usage 统计失败', 'error');
|
|
494
|
+
} finally {
|
|
495
|
+
this.sessionsUsageLoading = false;
|
|
496
|
+
if (loadSucceeded) {
|
|
497
|
+
this.sessionsUsageLoadedOnce = true;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
|
|
502
|
+
async loadSessions(options = {}) {
|
|
503
|
+
const result = await loadSessionsHelper.call(this, api, options || {});
|
|
364
504
|
this.pruneSessionPinnedMap(this.sessionsList);
|
|
365
505
|
return result;
|
|
366
506
|
},
|
|
367
507
|
|
|
368
508
|
async selectSession(session) {
|
|
369
|
-
if (!session)
|
|
370
|
-
|
|
509
|
+
if (!session) {
|
|
510
|
+
emitSessionLoadNativeDialog(this, 'selectSession:skip-empty');
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
emitSessionLoadNativeDialog(
|
|
514
|
+
this,
|
|
515
|
+
'selectSession:start',
|
|
516
|
+
`sessionId=${session.sessionId || ''}\nsource=${session.source || ''}`
|
|
517
|
+
);
|
|
518
|
+
const isSameSession = this.activeSession
|
|
519
|
+
&& this.getSessionExportKey(this.activeSession) === this.getSessionExportKey(session);
|
|
520
|
+
if (isSameSession) {
|
|
521
|
+
emitSessionLoadNativeDialog(this, 'selectSession:same-session', `sessionId=${session.sessionId || ''}`);
|
|
522
|
+
if (this.sessionDetailLoading) {
|
|
523
|
+
emitSessionLoadNativeDialog(this, 'selectSession:skip-detail-loading', `sessionId=${session.sessionId || ''}`);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const currentMessages = Array.isArray(this.activeSessionMessages) ? this.activeSessionMessages : [];
|
|
527
|
+
if (currentMessages.length > 0) {
|
|
528
|
+
emitSessionLoadNativeDialog(
|
|
529
|
+
this,
|
|
530
|
+
'selectSession:skip-existing-messages',
|
|
531
|
+
`sessionId=${session.sessionId || ''}\nmessages=${currentMessages.length}`
|
|
532
|
+
);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (typeof this.scheduleAfterFrame === 'function') {
|
|
536
|
+
const selectedSession = this.activeSession;
|
|
537
|
+
emitSessionLoadNativeDialog(this, 'selectSession:schedule-detail', `sessionId=${session.sessionId || ''}`);
|
|
538
|
+
this.scheduleAfterFrame(() => {
|
|
539
|
+
if (this.activeSession !== selectedSession) return;
|
|
540
|
+
void this.loadActiveSessionDetail();
|
|
541
|
+
});
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
emitSessionLoadNativeDialog(this, 'selectSession:load-detail-now', `sessionId=${session.sessionId || ''}`);
|
|
545
|
+
await this.loadActiveSessionDetail();
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
371
548
|
this.activeSession = session;
|
|
549
|
+
emitSessionLoadNativeDialog(this, 'selectSession:activate', `sessionId=${session.sessionId || ''}`);
|
|
550
|
+
if (typeof this.expandVisibleSessionList === 'function') {
|
|
551
|
+
this.expandVisibleSessionList(0, { ensureActive: true });
|
|
552
|
+
}
|
|
372
553
|
this.activeSessionMessages = [];
|
|
373
554
|
this.resetSessionDetailPagination();
|
|
374
555
|
this.resetSessionPreviewMessageRender();
|
|
@@ -377,6 +558,16 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
377
558
|
this.cancelSessionTimelineSync();
|
|
378
559
|
this.sessionTimelineActiveKey = '';
|
|
379
560
|
this.clearSessionTimelineRefs();
|
|
561
|
+
if (typeof this.scheduleAfterFrame === 'function') {
|
|
562
|
+
const selectedSession = this.activeSession;
|
|
563
|
+
emitSessionLoadNativeDialog(this, 'selectSession:schedule-detail', `sessionId=${session.sessionId || ''}`);
|
|
564
|
+
this.scheduleAfterFrame(() => {
|
|
565
|
+
if (this.activeSession !== selectedSession) return;
|
|
566
|
+
void this.loadActiveSessionDetail();
|
|
567
|
+
});
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
emitSessionLoadNativeDialog(this, 'selectSession:load-detail-now', `sessionId=${session.sessionId || ''}`);
|
|
380
571
|
await this.loadActiveSessionDetail();
|
|
381
572
|
},
|
|
382
573
|
|
|
@@ -22,6 +22,16 @@ export function createSessionTimelineMethods() {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
return {
|
|
25
|
+
hasRenderableSessionTimeline() {
|
|
26
|
+
return !!(
|
|
27
|
+
this.sessionTimelineEnabled
|
|
28
|
+
&& this.mainTab === 'sessions'
|
|
29
|
+
&& this.getMainTabForNav() === 'sessions'
|
|
30
|
+
&& this.sessionPreviewRenderEnabled
|
|
31
|
+
&& Array.isArray(this.sessionTimelineNodes)
|
|
32
|
+
&& this.sessionTimelineNodes.length
|
|
33
|
+
);
|
|
34
|
+
},
|
|
25
35
|
setSessionPreviewContainerRef(el) {
|
|
26
36
|
this.sessionPreviewContainerEl = el || null;
|
|
27
37
|
this.updateSessionTimelineOffset();
|
|
@@ -33,21 +43,6 @@ export function createSessionTimelineMethods() {
|
|
|
33
43
|
},
|
|
34
44
|
observeSessionPreviewHeaderResize() {
|
|
35
45
|
this.disconnectSessionPreviewHeaderResizeObserver();
|
|
36
|
-
if (!this.sessionPreviewHeaderEl || typeof ResizeObserver !== 'function') return;
|
|
37
|
-
this.sessionPreviewHeaderResizeObserver = new ResizeObserver(() => {
|
|
38
|
-
this.updateSessionTimelineOffset();
|
|
39
|
-
this.invalidateSessionTimelineMeasurementCache();
|
|
40
|
-
if (
|
|
41
|
-
this.sessionTimelineEnabled
|
|
42
|
-
&& this.mainTab === 'sessions'
|
|
43
|
-
&& this.getMainTabForNav() === 'sessions'
|
|
44
|
-
&& this.sessionPreviewRenderEnabled
|
|
45
|
-
&& this.sessionTimelineNodes.length
|
|
46
|
-
) {
|
|
47
|
-
this.scheduleSessionTimelineSync();
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
this.sessionPreviewHeaderResizeObserver.observe(this.sessionPreviewHeaderEl);
|
|
51
46
|
},
|
|
52
47
|
setSessionPreviewHeaderRef(el) {
|
|
53
48
|
this.disconnectSessionPreviewHeaderResizeObserver();
|
|
@@ -191,7 +186,18 @@ export function createSessionTimelineMethods() {
|
|
|
191
186
|
updateSessionTimelineOffset() {
|
|
192
187
|
const container = this.sessionPreviewContainerEl || this.$refs.sessionPreviewContainer;
|
|
193
188
|
if (!container || !container.style) return;
|
|
189
|
+
if (!this.hasRenderableSessionTimeline()) {
|
|
190
|
+
if (this.__sessionPreviewHeaderOffsetPx != null) {
|
|
191
|
+
container.style.removeProperty('--session-preview-header-offset');
|
|
192
|
+
this.__sessionPreviewHeaderOffsetPx = null;
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
194
196
|
const offset = getSessionPreviewHeaderOffset(this);
|
|
197
|
+
if (this.__sessionPreviewHeaderOffsetPx === offset) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
this.__sessionPreviewHeaderOffsetPx = offset;
|
|
195
201
|
container.style.setProperty('--session-preview-header-offset', `${offset}px`);
|
|
196
202
|
},
|
|
197
203
|
bindSessionMessageRef(messageKey, el, ticket = this.sessionTabRenderTicket) {
|
|
@@ -237,6 +243,7 @@ export function createSessionTimelineMethods() {
|
|
|
237
243
|
this.sessionTimelineRafId = 0;
|
|
238
244
|
},
|
|
239
245
|
scheduleSessionTimelineSync() {
|
|
246
|
+
this.updateSessionTimelineOffset();
|
|
240
247
|
if (this.sessionTimelineRafId) return;
|
|
241
248
|
if (typeof requestAnimationFrame === 'function') {
|
|
242
249
|
this.sessionTimelineRafId = requestAnimationFrame(() => {
|
|
@@ -340,6 +340,9 @@ export function createSessionTrashMethods(options = {}) {
|
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
342
|
this.showMessage('会话已恢复', 'success');
|
|
343
|
+
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
344
|
+
this.invalidateSessionsUsageData({ preserveList: true });
|
|
345
|
+
}
|
|
343
346
|
this.invalidateSessionTrashRequests();
|
|
344
347
|
await this.loadSessionTrash({ forceRefresh: true });
|
|
345
348
|
if (this.sessionsLoadedOnce) {
|