@raolin2025/claude-code-node 2.8.16 → 2.8.17
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raolin2025/claude-code-node",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.17",
|
|
4
4
|
"description": "Node.js AI Code Agent CLI - Zero dependencies, pure JavaScript, security hardened, multi-channel notifications, Telegram & QQ Bot remote programming, rich media upload, multi-account management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/core/index.js",
|
|
@@ -226,3 +226,29 @@ test('max_tokens:绝不超过窗口一半(防超窗)', async () => {
|
|
|
226
226
|
const qe2 = new QueryEngine({ tokenBudget: new TokenBudget({ maxTokens: 10000 }), outputRatio: 1.0 })
|
|
227
227
|
assert.ok(qe2._computeMaxOutputTokens() <= 5000, `max_tokens=${qe2._computeMaxOutputTokens()} 不应超过窗口一半 5000`)
|
|
228
228
|
})
|
|
229
|
+
|
|
230
|
+
// ---- _buildRequest 把 system 统一前置(防 llama.cpp 500)----
|
|
231
|
+
test('_buildRequest:把中间 system 统一前置到开头', async () => {
|
|
232
|
+
const { QueryEngine } = await import('../core/query-engine.js')
|
|
233
|
+
const qe = new QueryEngine({ systemPrompt: 'SYS-ROOT', tools: [] })
|
|
234
|
+
// 模拟 state.messages 里 system 摘要被插到中间(折叠/恢复导致)
|
|
235
|
+
const messages = [
|
|
236
|
+
{ role: 'user', content: 'u1' },
|
|
237
|
+
{ role: 'assistant', content: 'a1' },
|
|
238
|
+
{ role: 'system', content: '[Context Summary] 中间摘要' },
|
|
239
|
+
{ role: 'user', content: 'u2' },
|
|
240
|
+
]
|
|
241
|
+
const req = qe._buildRequest(messages)
|
|
242
|
+
// 验证:所有 system 在开头,中间无 system
|
|
243
|
+
let seenBody = false, badSystem = false
|
|
244
|
+
for (const m of req) {
|
|
245
|
+
if (m.role !== 'system') seenBody = true
|
|
246
|
+
else if (seenBody) badSystem = true
|
|
247
|
+
}
|
|
248
|
+
assert.equal(badSystem, false, '中间不应出现 system(否则 llama.cpp 报 500)')
|
|
249
|
+
// 第一条是 system
|
|
250
|
+
assert.equal(req[0].role, 'system')
|
|
251
|
+
// 原始顺序(非 system 部分)应保持
|
|
252
|
+
const nonSys = req.filter(m => m.role !== 'system').map(m => m.role)
|
|
253
|
+
assert.deepEqual(nonSys, ['user', 'assistant', 'user'])
|
|
254
|
+
})
|
package/src/core/query-engine.js
CHANGED
|
@@ -358,10 +358,25 @@ export class QueryEngine {
|
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
// 历史消息 — 转换为 OpenAI 兼容格式
|
|
361
|
+
// 关键:把所有 system 消息【收集到一起放到最前面】,而不是原样透传。
|
|
362
|
+
// 原因:llama.cpp/Jinja 严格要求 system 消息必须在对话开头,中间出现 system
|
|
363
|
+
// 会报 "System message must be at the beginning" (500)。
|
|
364
|
+
// 折叠/压缩/引导注入可能在 state.messages 中间留下 system 摘要消息,
|
|
365
|
+
// 这里统一前置,彻底规避该错误。
|
|
366
|
+
const systemMsgs = []
|
|
367
|
+
const bodyMsgs = []
|
|
361
368
|
for (const msg of messages) {
|
|
362
369
|
if (msg.role === 'system') {
|
|
363
|
-
|
|
364
|
-
} else
|
|
370
|
+
systemMsgs.push(msg)
|
|
371
|
+
} else {
|
|
372
|
+
bodyMsgs.push(msg)
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
for (const msg of systemMsgs) {
|
|
376
|
+
request.push({ role: 'system', content: msg.content })
|
|
377
|
+
}
|
|
378
|
+
for (const msg of bodyMsgs) {
|
|
379
|
+
if (msg.role === 'user') {
|
|
365
380
|
request.push({ role: 'user', content: this._buildUserContent(msg) })
|
|
366
381
|
} else if (msg.role === 'assistant') {
|
|
367
382
|
// 构建 assistant 消息基础
|