codexmate 0.0.12 → 0.0.14
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.en.md +429 -0
- package/README.md +241 -203
- package/cli.js +10210 -0
- package/doc/CHANGELOG.md +14 -1
- package/doc/CHANGELOG.zh-CN.md +13 -0
- package/lib/cli-utils.js +16 -0
- package/lib/mcp-stdio.js +440 -0
- package/lib/workflow-engine.js +340 -0
- package/package.json +63 -53
- package/web-ui/app.js +1417 -14
- package/web-ui/index.html +585 -67
- package/web-ui/logic.mjs +147 -1
- package/web-ui/styles.css +1049 -66
- package/README.zh-CN.md +0 -397
- package/src/cli.js +0 -5464
- package/src/lib/cli-file-utils.js +0 -151
- package/src/lib/cli-models-utils.js +0 -152
- package/src/lib/cli-network-utils.js +0 -148
- package/src/lib/cli-session-utils.js +0 -121
- package/src/lib/cli-utils.js +0 -139
- package/src/res/json5.min.js +0 -1
- package/src/res/logo.png +0 -0
- package/src/res/screenshot.png +0 -0
- package/src/res/vue.global.js +0 -18552
- package/src/web-ui/app.js +0 -2970
- package/src/web-ui/index.html +0 -1310
- package/src/web-ui/logic.mjs +0 -157
- package/src/web-ui/styles.css +0 -2868
- /package/{src/web-ui.html → web-ui.html} +0 -0
package/web-ui/logic.mjs
CHANGED
|
@@ -128,10 +128,31 @@ export function buildSpeedTestIssue(name, result) {
|
|
|
128
128
|
|
|
129
129
|
// Session filtering helpers
|
|
130
130
|
export function isSessionQueryEnabled(source) {
|
|
131
|
-
const normalized = (source
|
|
131
|
+
const normalized = normalizeSessionSource(source, '');
|
|
132
132
|
return normalized === 'codex' || normalized === 'claude' || normalized === 'all';
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
export function normalizeSessionSource(source, fallback = 'all') {
|
|
136
|
+
const normalized = typeof source === 'string'
|
|
137
|
+
? source.trim().toLowerCase()
|
|
138
|
+
: '';
|
|
139
|
+
if (normalized === 'codex' || normalized === 'claude' || normalized === 'all') {
|
|
140
|
+
return normalized;
|
|
141
|
+
}
|
|
142
|
+
return fallback;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function normalizeSessionPathFilter(pathFilter) {
|
|
146
|
+
return typeof pathFilter === 'string' ? pathFilter.trim() : '';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function buildSessionFilterCacheState(source, pathFilter) {
|
|
150
|
+
return {
|
|
151
|
+
source: normalizeSessionSource(source, 'all'),
|
|
152
|
+
pathFilter: normalizeSessionPathFilter(pathFilter)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
135
156
|
export function buildSessionListParams(options = {}) {
|
|
136
157
|
const {
|
|
137
158
|
source = 'all',
|
|
@@ -155,3 +176,128 @@ export function buildSessionListParams(options = {}) {
|
|
|
155
176
|
forceRefresh: true
|
|
156
177
|
};
|
|
157
178
|
}
|
|
179
|
+
|
|
180
|
+
export function normalizeSessionMessageRole(role) {
|
|
181
|
+
const value = typeof role === 'string' ? role.trim().toLowerCase() : '';
|
|
182
|
+
if (value === 'user' || value === 'assistant' || value === 'system') {
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
return 'assistant';
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function toRoleMeta(role) {
|
|
189
|
+
if (role === 'user') {
|
|
190
|
+
return { role: 'user', roleLabel: 'User', roleShort: 'U' };
|
|
191
|
+
}
|
|
192
|
+
if (role === 'assistant') {
|
|
193
|
+
return { role: 'assistant', roleLabel: 'Assistant', roleShort: 'A' };
|
|
194
|
+
}
|
|
195
|
+
if (role === 'system') {
|
|
196
|
+
return { role: 'system', roleLabel: 'System', roleShort: 'S' };
|
|
197
|
+
}
|
|
198
|
+
return { role: 'mixed', roleLabel: 'Mixed', roleShort: 'M' };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function clampTimelinePercent(percent) {
|
|
202
|
+
return Math.max(6, Math.min(94, percent));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function formatSessionTimelineTimestamp(timestamp) {
|
|
206
|
+
const value = typeof timestamp === 'string' ? timestamp.trim() : '';
|
|
207
|
+
if (!value) return '';
|
|
208
|
+
|
|
209
|
+
// 优先按 ISO/常见时间串抽取,避免本地时区格式差异导致的展示抖动。
|
|
210
|
+
const matched = value.match(/^(\d{4})-(\d{2})-(\d{2})[T\s](\d{2}):(\d{2})(?::(\d{2}))?/);
|
|
211
|
+
if (matched) {
|
|
212
|
+
const second = matched[6] || '00';
|
|
213
|
+
return `${matched[2]}-${matched[3]} ${matched[4]}:${matched[5]}:${second}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function buildSessionTimelineNodes(messages = [], options = {}) {
|
|
220
|
+
const list = Array.isArray(messages) ? messages : [];
|
|
221
|
+
const getKey = typeof options.getKey === 'function'
|
|
222
|
+
? options.getKey
|
|
223
|
+
: ((_message, index) => `msg-${index}`);
|
|
224
|
+
const total = list.length;
|
|
225
|
+
const rawMaxMarkers = Number(options.maxMarkers);
|
|
226
|
+
const maxMarkers = Number.isFinite(rawMaxMarkers)
|
|
227
|
+
? Math.max(1, Math.min(80, Math.floor(rawMaxMarkers)))
|
|
228
|
+
: 30;
|
|
229
|
+
|
|
230
|
+
const buildSingleNode = (message, index) => {
|
|
231
|
+
const role = normalizeSessionMessageRole(message && (message.normalizedRole || message.role));
|
|
232
|
+
const roleMeta = toRoleMeta(role);
|
|
233
|
+
const key = String(getKey(message, index) || `msg-${index}`);
|
|
234
|
+
const displayTime = formatSessionTimelineTimestamp(message && message.timestamp ? message.timestamp : '');
|
|
235
|
+
const title = displayTime
|
|
236
|
+
? `#${index + 1} · ${roleMeta.roleLabel} · ${displayTime}`
|
|
237
|
+
: `#${index + 1} · ${roleMeta.roleLabel}`;
|
|
238
|
+
const percent = total <= 1 ? 0 : (index / (total - 1)) * 100;
|
|
239
|
+
return {
|
|
240
|
+
key,
|
|
241
|
+
role: roleMeta.role,
|
|
242
|
+
roleLabel: roleMeta.roleLabel,
|
|
243
|
+
roleShort: roleMeta.roleShort,
|
|
244
|
+
displayTime,
|
|
245
|
+
title,
|
|
246
|
+
percent,
|
|
247
|
+
safePercent: clampTimelinePercent(percent)
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
if (total <= maxMarkers) {
|
|
252
|
+
return list.map((message, index) => buildSingleNode(message, index));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const nodes = [];
|
|
256
|
+
const bucketWidth = total / maxMarkers;
|
|
257
|
+
for (let bucket = 0; bucket < maxMarkers; bucket += 1) {
|
|
258
|
+
let start = Math.floor(bucket * bucketWidth);
|
|
259
|
+
if (nodes.length && start <= nodes[nodes.length - 1].endIndex) {
|
|
260
|
+
start = nodes[nodes.length - 1].endIndex + 1;
|
|
261
|
+
}
|
|
262
|
+
if (start >= total) {
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
let end = Math.floor((bucket + 1) * bucketWidth) - 1;
|
|
266
|
+
end = Math.max(start, Math.min(total - 1, end));
|
|
267
|
+
const targetIndex = Math.min(total - 1, start + Math.floor((end - start) / 2));
|
|
268
|
+
const targetMessage = list[targetIndex] || null;
|
|
269
|
+
const key = String(getKey(targetMessage, targetIndex) || `msg-${targetIndex}`);
|
|
270
|
+
const percent = total <= 1 ? 0 : (targetIndex / (total - 1)) * 100;
|
|
271
|
+
const messagesInGroup = end - start + 1;
|
|
272
|
+
const roleSet = new Set();
|
|
273
|
+
for (let i = start; i <= end; i += 1) {
|
|
274
|
+
roleSet.add(normalizeSessionMessageRole(list[i] && (list[i].normalizedRole || list[i].role)));
|
|
275
|
+
}
|
|
276
|
+
const roleValue = roleSet.size === 1 ? Array.from(roleSet)[0] : 'mixed';
|
|
277
|
+
const roleMeta = toRoleMeta(roleValue);
|
|
278
|
+
const firstTime = formatSessionTimelineTimestamp(list[start] && list[start].timestamp ? list[start].timestamp : '');
|
|
279
|
+
const lastTime = formatSessionTimelineTimestamp(list[end] && list[end].timestamp ? list[end].timestamp : '');
|
|
280
|
+
let displayTime = '';
|
|
281
|
+
if (firstTime && lastTime) {
|
|
282
|
+
displayTime = firstTime === lastTime ? firstTime : `${firstTime} ~ ${lastTime}`;
|
|
283
|
+
} else {
|
|
284
|
+
displayTime = firstTime || lastTime;
|
|
285
|
+
}
|
|
286
|
+
const titleBase = `#${start + 1}-${end + 1} · ${messagesInGroup} msgs · ${roleMeta.roleLabel}`;
|
|
287
|
+
const title = displayTime ? `${titleBase} · ${displayTime}` : titleBase;
|
|
288
|
+
nodes.push({
|
|
289
|
+
key,
|
|
290
|
+
role: roleMeta.role,
|
|
291
|
+
roleLabel: roleMeta.roleLabel,
|
|
292
|
+
roleShort: roleMeta.roleShort,
|
|
293
|
+
displayTime,
|
|
294
|
+
title,
|
|
295
|
+
percent,
|
|
296
|
+
safePercent: clampTimelinePercent(percent),
|
|
297
|
+
startIndex: start,
|
|
298
|
+
endIndex: end,
|
|
299
|
+
messageCount: messagesInGroup
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return nodes;
|
|
303
|
+
}
|