coding-tool-x 3.3.2 → 3.3.4
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/dist/web/assets/{Analytics-DtR00OYP.js → Analytics-B6CWdkhx.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-DWiSFOp5.js → ConfigTemplates-BW6LEgd8.js} +1 -1
- package/dist/web/assets/{Home-DUu2mGb6.js → Home-B2B2gS2-.js} +1 -1
- package/dist/web/assets/{PluginManager-DsJ1KtNr.js → PluginManager-Bqc7ldY-.js} +1 -1
- package/dist/web/assets/{ProjectList-CzTJaBJb.js → ProjectList-BFdZZm_8.js} +1 -1
- package/dist/web/assets/{SessionList-D1ovPZ0I.js → SessionList-B_Tp37kM.js} +1 -1
- package/dist/web/assets/{SkillManager-DqpDTc2c.js → SkillManager-ul2rcS3o.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-Dj28-3G5.js → WorkspaceManager-Dp5Jvdtu.js} +1 -1
- package/dist/web/assets/index-CSBDZxYn.js +2 -0
- package/dist/web/assets/index-DxRneGyu.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/server/api/claude-hooks.js +26 -3
- package/src/server/api/codex-proxy.js +15 -3
- package/src/server/api/codex-sessions.js +6 -5
- package/src/server/api/gemini-proxy.js +15 -3
- package/src/server/api/opencode-proxy.js +15 -3
- package/src/server/api/proxy.js +23 -2
- package/src/server/api/sessions.js +36 -6
- package/src/server/opencode-proxy-server.js +11 -1
- package/src/server/services/codex-parser.js +31 -4
- package/src/server/services/opencode-sessions.js +28 -3
- package/dist/web/assets/index-CaKktouI.js +0 -2
- package/dist/web/assets/index-DZjDFGqR.css +0 -1
|
@@ -279,6 +279,7 @@ module.exports = (config) => {
|
|
|
279
279
|
|
|
280
280
|
const stream = fs.createReadStream(sessionFile, { encoding: 'utf8' });
|
|
281
281
|
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
282
|
+
let lastAssistantModel = null;
|
|
282
283
|
|
|
283
284
|
try {
|
|
284
285
|
for await (const line of rl) {
|
|
@@ -297,31 +298,45 @@ module.exports = (config) => {
|
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
if (json.type === 'user' || json.type === 'assistant') {
|
|
301
|
+
const resolvedModel = json.message?.model || json.model || lastAssistantModel || null;
|
|
302
|
+
const messageId = json.message?.id || json.uuid || null;
|
|
300
303
|
const message = {
|
|
301
304
|
type: json.type,
|
|
302
305
|
content: null,
|
|
303
306
|
timestamp: json.timestamp || null,
|
|
304
|
-
model:
|
|
307
|
+
model: resolvedModel,
|
|
308
|
+
messageId,
|
|
309
|
+
subtype: null
|
|
305
310
|
};
|
|
311
|
+
let deferredToolResultContent = '';
|
|
306
312
|
|
|
307
313
|
if (json.type === 'user') {
|
|
308
314
|
if (typeof json.message?.content === 'string') {
|
|
309
315
|
message.content = json.message.content;
|
|
310
316
|
} else if (Array.isArray(json.message?.content)) {
|
|
311
|
-
const
|
|
317
|
+
const userParts = [];
|
|
318
|
+
const toolResultParts = [];
|
|
312
319
|
for (const item of json.message.content) {
|
|
313
320
|
if (item.type === 'text' && item.text) {
|
|
314
|
-
|
|
321
|
+
userParts.push(item.text);
|
|
315
322
|
} else if (item.type === 'tool_result') {
|
|
316
323
|
const resultContent = typeof item.content === 'string'
|
|
317
324
|
? item.content
|
|
318
325
|
: JSON.stringify(item.content, null, 2);
|
|
319
|
-
|
|
326
|
+
toolResultParts.push(`**[工具结果]**\n\`\`\`\n${resultContent}\n\`\`\``);
|
|
320
327
|
} else if (item.type === 'image') {
|
|
321
|
-
|
|
328
|
+
userParts.push('[图片]');
|
|
322
329
|
}
|
|
323
330
|
}
|
|
324
|
-
|
|
331
|
+
|
|
332
|
+
if (userParts.length > 0) {
|
|
333
|
+
message.content = userParts.join('\n\n');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Claude tool_result is carried in a "user" envelope, but should be rendered as AI tool output.
|
|
337
|
+
if (toolResultParts.length > 0) {
|
|
338
|
+
deferredToolResultContent = toolResultParts.join('\n\n');
|
|
339
|
+
}
|
|
325
340
|
}
|
|
326
341
|
} else if (json.type === 'assistant') {
|
|
327
342
|
if (Array.isArray(json.message?.content)) {
|
|
@@ -340,11 +355,26 @@ module.exports = (config) => {
|
|
|
340
355
|
} else if (typeof json.message?.content === 'string') {
|
|
341
356
|
message.content = json.message.content;
|
|
342
357
|
}
|
|
358
|
+
|
|
359
|
+
if (message.model) {
|
|
360
|
+
lastAssistantModel = message.model;
|
|
361
|
+
}
|
|
343
362
|
}
|
|
344
363
|
|
|
345
364
|
if (message.content && message.content !== 'Warmup') {
|
|
346
365
|
allMessages.push(message);
|
|
347
366
|
}
|
|
367
|
+
|
|
368
|
+
if (deferredToolResultContent) {
|
|
369
|
+
allMessages.push({
|
|
370
|
+
type: 'assistant',
|
|
371
|
+
subtype: 'tool_result',
|
|
372
|
+
content: deferredToolResultContent,
|
|
373
|
+
timestamp: json.timestamp || null,
|
|
374
|
+
model: resolvedModel,
|
|
375
|
+
messageId: messageId ? `${messageId}-tool-result` : null
|
|
376
|
+
});
|
|
377
|
+
}
|
|
348
378
|
}
|
|
349
379
|
} catch (err) {
|
|
350
380
|
// Skip invalid lines
|
|
@@ -2125,6 +2125,16 @@ function sendChatCompletionsSse(res, responseObject) {
|
|
|
2125
2125
|
const message = responseObject?.choices?.[0]?.message || {};
|
|
2126
2126
|
const text = message?.content || '';
|
|
2127
2127
|
const toolCalls = Array.isArray(message?.tool_calls) ? message.tool_calls : [];
|
|
2128
|
+
const streamedToolCalls = toolCalls.map((toolCall, index) => {
|
|
2129
|
+
const numericIndex = Number(toolCall?.index);
|
|
2130
|
+
const normalizedIndex = Number.isFinite(numericIndex) ? numericIndex : index;
|
|
2131
|
+
|
|
2132
|
+
if (toolCall && typeof toolCall === 'object' && !Array.isArray(toolCall)) {
|
|
2133
|
+
return { ...toolCall, index: normalizedIndex };
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
return { index: normalizedIndex };
|
|
2137
|
+
});
|
|
2128
2138
|
const finishReason = responseObject?.choices?.[0]?.finish_reason || 'stop';
|
|
2129
2139
|
|
|
2130
2140
|
setSseHeaders(res);
|
|
@@ -2140,7 +2150,7 @@ function sendChatCompletionsSse(res, responseObject) {
|
|
|
2140
2150
|
delta: {
|
|
2141
2151
|
role: 'assistant',
|
|
2142
2152
|
...(text ? { content: text } : {}),
|
|
2143
|
-
...(
|
|
2153
|
+
...(streamedToolCalls.length > 0 ? { tool_calls: streamedToolCalls } : {})
|
|
2144
2154
|
},
|
|
2145
2155
|
finish_reason: null
|
|
2146
2156
|
}
|
|
@@ -63,11 +63,22 @@ function extractSessionMeta(lines) {
|
|
|
63
63
|
*/
|
|
64
64
|
function extractMessages(lines) {
|
|
65
65
|
const messages = [];
|
|
66
|
+
let currentTurnModel = null;
|
|
67
|
+
let lastAssistantModel = null;
|
|
66
68
|
|
|
67
69
|
lines.forEach(line => {
|
|
70
|
+
if (line.type === 'turn_context') {
|
|
71
|
+
const model = line.payload?.model;
|
|
72
|
+
if (typeof model === 'string' && model.trim()) {
|
|
73
|
+
currentTurnModel = model.trim();
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
68
78
|
if (line.type !== 'response_item') return;
|
|
69
79
|
|
|
70
80
|
const payload = line.payload;
|
|
81
|
+
const resolvedModel = payload?.model || currentTurnModel || lastAssistantModel || null;
|
|
71
82
|
|
|
72
83
|
// 用户/助手消息
|
|
73
84
|
if (payload.type === 'message') {
|
|
@@ -81,8 +92,12 @@ function extractMessages(lines) {
|
|
|
81
92
|
messages.push({
|
|
82
93
|
role: payload.role,
|
|
83
94
|
content: text,
|
|
84
|
-
timestamp: line.timestamp
|
|
95
|
+
timestamp: line.timestamp,
|
|
96
|
+
model: payload.role === 'assistant' ? resolvedModel : null
|
|
85
97
|
});
|
|
98
|
+
if (payload.role === 'assistant' && resolvedModel) {
|
|
99
|
+
lastAssistantModel = resolvedModel;
|
|
100
|
+
}
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
103
|
|
|
@@ -101,8 +116,12 @@ function extractMessages(lines) {
|
|
|
101
116
|
name: payload.name,
|
|
102
117
|
arguments: parsedArguments,
|
|
103
118
|
callId: payload.call_id,
|
|
104
|
-
timestamp: line.timestamp
|
|
119
|
+
timestamp: line.timestamp,
|
|
120
|
+
model: resolvedModel
|
|
105
121
|
});
|
|
122
|
+
if (resolvedModel) {
|
|
123
|
+
lastAssistantModel = resolvedModel;
|
|
124
|
+
}
|
|
106
125
|
}
|
|
107
126
|
|
|
108
127
|
// 工具输出
|
|
@@ -119,8 +138,12 @@ function extractMessages(lines) {
|
|
|
119
138
|
role: 'tool_output',
|
|
120
139
|
callId: payload.call_id,
|
|
121
140
|
output: parsedOutput,
|
|
122
|
-
timestamp: line.timestamp
|
|
141
|
+
timestamp: line.timestamp,
|
|
142
|
+
model: resolvedModel
|
|
123
143
|
});
|
|
144
|
+
if (resolvedModel) {
|
|
145
|
+
lastAssistantModel = resolvedModel;
|
|
146
|
+
}
|
|
124
147
|
}
|
|
125
148
|
|
|
126
149
|
// 推理内容
|
|
@@ -135,8 +158,12 @@ function extractMessages(lines) {
|
|
|
135
158
|
messages.push({
|
|
136
159
|
role: 'reasoning',
|
|
137
160
|
content: text,
|
|
138
|
-
timestamp: line.timestamp
|
|
161
|
+
timestamp: line.timestamp,
|
|
162
|
+
model: resolvedModel
|
|
139
163
|
});
|
|
164
|
+
if (resolvedModel) {
|
|
165
|
+
lastAssistantModel = resolvedModel;
|
|
166
|
+
}
|
|
140
167
|
}
|
|
141
168
|
}
|
|
142
169
|
});
|
|
@@ -359,7 +359,19 @@ function getSessionRowsByProjectId(projectId) {
|
|
|
359
359
|
s.time_created,
|
|
360
360
|
s.time_updated,
|
|
361
361
|
s.time_compacting,
|
|
362
|
-
s.time_archived
|
|
362
|
+
s.time_archived,
|
|
363
|
+
(
|
|
364
|
+
COALESCE((
|
|
365
|
+
SELECT SUM(length(CAST(COALESCE(m.data, '') AS BLOB)))
|
|
366
|
+
FROM message m
|
|
367
|
+
WHERE m.session_id = s.id
|
|
368
|
+
), 0) +
|
|
369
|
+
COALESCE((
|
|
370
|
+
SELECT SUM(length(CAST(COALESCE(p.data, '') AS BLOB)))
|
|
371
|
+
FROM part p
|
|
372
|
+
WHERE p.session_id = s.id
|
|
373
|
+
), 0)
|
|
374
|
+
) AS size
|
|
363
375
|
FROM session s
|
|
364
376
|
WHERE s.project_id = ${sqlQuote(projectId)}
|
|
365
377
|
AND s.time_archived IS NULL
|
|
@@ -387,7 +399,19 @@ function getSessionRowById(sessionId) {
|
|
|
387
399
|
s.time_created,
|
|
388
400
|
s.time_updated,
|
|
389
401
|
s.time_compacting,
|
|
390
|
-
s.time_archived
|
|
402
|
+
s.time_archived,
|
|
403
|
+
(
|
|
404
|
+
COALESCE((
|
|
405
|
+
SELECT SUM(length(CAST(COALESCE(m.data, '') AS BLOB)))
|
|
406
|
+
FROM message m
|
|
407
|
+
WHERE m.session_id = s.id
|
|
408
|
+
), 0) +
|
|
409
|
+
COALESCE((
|
|
410
|
+
SELECT SUM(length(CAST(COALESCE(p.data, '') AS BLOB)))
|
|
411
|
+
FROM part p
|
|
412
|
+
WHERE p.session_id = s.id
|
|
413
|
+
), 0)
|
|
414
|
+
) AS size
|
|
391
415
|
FROM session s
|
|
392
416
|
WHERE s.id = ${sqlQuote(sessionId)}
|
|
393
417
|
LIMIT 1
|
|
@@ -426,11 +450,12 @@ function getPartRowsBySessionId(sessionId) {
|
|
|
426
450
|
}
|
|
427
451
|
|
|
428
452
|
function normalizeSession(session, projectId = null) {
|
|
453
|
+
const size = Number(session?.size);
|
|
429
454
|
return {
|
|
430
455
|
sessionId: session.id,
|
|
431
456
|
projectName: projectId || session.project_id,
|
|
432
457
|
mtime: toIsoTime(session.time_updated) || new Date().toISOString(),
|
|
433
|
-
size: 0,
|
|
458
|
+
size: Number.isFinite(size) && size > 0 ? size : 0,
|
|
434
459
|
filePath: '',
|
|
435
460
|
gitBranch: null,
|
|
436
461
|
firstMessage: session.title || session.slug || null,
|