@riconext/hermes-repo 1.2.2 → 1.2.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/CHANGELOG.md +12 -0
- package/dist/cli.js +105 -16
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 089eb55: 兼容 LLM 返回 path 和 YAML frontmatter 的知识文件格式,避免有效知识文件在 flush 时被过滤丢弃。
|
|
8
|
+
|
|
9
|
+
## 1.2.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 17d33f3: 增加 flush 调用 LLM 时的详细 debug 日志,便于检查请求输入、原始响应和标准化后的知识文件结果。
|
|
14
|
+
|
|
3
15
|
## 1.2.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/cli.js
CHANGED
|
@@ -62,6 +62,16 @@ function debugLog(enabled, phase, message) {
|
|
|
62
62
|
console.error(line);
|
|
63
63
|
writeToLogFile(line);
|
|
64
64
|
}
|
|
65
|
+
function debugLogBlock(enabled, phase, label, content) {
|
|
66
|
+
if (!enabled) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
debugLog(true, phase, `${label} BEGIN`);
|
|
70
|
+
for (const line of content.split(/\r?\n/)) {
|
|
71
|
+
debugLog(true, phase, `| ${line}`);
|
|
72
|
+
}
|
|
73
|
+
debugLog(true, phase, `${label} END`);
|
|
74
|
+
}
|
|
65
75
|
function debugFromContext(ctx, phase, message) {
|
|
66
76
|
debugLog(ctx?.config.debug === true, phase, message);
|
|
67
77
|
}
|
|
@@ -1339,7 +1349,11 @@ var CONSOLIDATE_SYSTEM_PROMPT = `\u4F60\u662F\u4E00\u4E2A\u9879\u76EE\u77E5\u8BC
|
|
|
1339
1349
|
## \u8F93\u51FA\u8981\u6C42
|
|
1340
1350
|
- \u8F93\u51FA\u4E25\u683C JSON \u683C\u5F0F
|
|
1341
1351
|
- knowledgeFiles \u6570\u7EC4\u5305\u542B\u6240\u6709\u9700\u8981\u521B\u5EFA/\u66F4\u65B0\u7684\u6587\u4EF6
|
|
1342
|
-
- \u6BCF\u9879\u5FC5\u987B\u5305\u542B\
|
|
1352
|
+
- \u6BCF\u9879\u5FC5\u987B\u5305\u542B targetPath\u3001action\u3001frontmatter\u3001body
|
|
1353
|
+
- targetPath \u662F\u76F8\u5BF9 .memory/ \u7684\u8DEF\u5F84\uFF0C\u4F8B\u5982 "domains/canvas/canvas-interaction.md"
|
|
1354
|
+
- \u4E0D\u8981\u4F7F\u7528 path\u3001filePath\u3001filename \u7B49\u5B57\u6BB5\u4EE3\u66FF targetPath
|
|
1355
|
+
- frontmatter \u5FC5\u987B\u662F JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA YAML \u5B57\u7B26\u4E32
|
|
1356
|
+
- body \u662F\u4E0D\u5305\u542B frontmatter \u7684 markdown \u6B63\u6587
|
|
1343
1357
|
- memoryMd \u662F\u5B8C\u6574 MEMORY.md \u5185\u5BB9
|
|
1344
1358
|
- \u65E0\u4EF7\u503C\u7684 session \u5728 skippedSessions \u4E2D\u8BF4\u660E\u539F\u56E0\uFF08\u800C\u975E\u751F\u6210\u7A7A\u5185\u5BB9\uFF09`;
|
|
1345
1359
|
function scanExistingKnowledge(repoRoot) {
|
|
@@ -1423,7 +1437,7 @@ function buildLlmConsolidateInput(repoRoot, sessions) {
|
|
|
1423
1437
|
currentMemoryMd
|
|
1424
1438
|
};
|
|
1425
1439
|
}
|
|
1426
|
-
async function callLlmConsolidate(input2, llmConfig) {
|
|
1440
|
+
async function callLlmConsolidate(input2, llmConfig, debug = false) {
|
|
1427
1441
|
if (!llmConfig.enabled) {
|
|
1428
1442
|
throw new Error(
|
|
1429
1443
|
"LLM \u672A\u542F\u7528\uFF1A\u8BF7\u5728 config.json \u4E2D\u8BBE\u7F6E llm.enabled = true"
|
|
@@ -1436,6 +1450,23 @@ async function callLlmConsolidate(input2, llmConfig) {
|
|
|
1436
1450
|
}
|
|
1437
1451
|
const url = `${llmConfig.baseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
1438
1452
|
const userContent = formatUserMessage(input2);
|
|
1453
|
+
debugLog(
|
|
1454
|
+
debug,
|
|
1455
|
+
"llm",
|
|
1456
|
+
`request: provider=${llmConfig.provider}, model=${llmConfig.model}, baseUrl=${llmConfig.baseUrl}, pendingSessions=${input2.pendingSessions.length}, existingKnowledge=${input2.existingKnowledge.length}, currentMemoryChars=${input2.currentMemoryMd?.length ?? 0}`
|
|
1457
|
+
);
|
|
1458
|
+
debugLogBlock(debug, "llm", "system prompt", CONSOLIDATE_SYSTEM_PROMPT);
|
|
1459
|
+
debugLogBlock(debug, "llm", "user input", userContent);
|
|
1460
|
+
const requestBody = {
|
|
1461
|
+
model: llmConfig.model,
|
|
1462
|
+
response_format: { type: "json_object" },
|
|
1463
|
+
messages: [
|
|
1464
|
+
{ role: "system", content: CONSOLIDATE_SYSTEM_PROMPT },
|
|
1465
|
+
{ role: "user", content: userContent }
|
|
1466
|
+
],
|
|
1467
|
+
temperature: 0.2
|
|
1468
|
+
};
|
|
1469
|
+
debugLogBlock(debug, "llm", "request body", JSON.stringify(requestBody, null, 2));
|
|
1439
1470
|
const controller = new AbortController();
|
|
1440
1471
|
const timeout = setTimeout(() => controller.abort(), 12e4);
|
|
1441
1472
|
try {
|
|
@@ -1445,35 +1476,58 @@ async function callLlmConsolidate(input2, llmConfig) {
|
|
|
1445
1476
|
"Content-Type": "application/json",
|
|
1446
1477
|
Authorization: `Bearer ${llmConfig.apiKey}`
|
|
1447
1478
|
},
|
|
1448
|
-
body: JSON.stringify(
|
|
1449
|
-
model: llmConfig.model,
|
|
1450
|
-
response_format: { type: "json_object" },
|
|
1451
|
-
messages: [
|
|
1452
|
-
{ role: "system", content: CONSOLIDATE_SYSTEM_PROMPT },
|
|
1453
|
-
{ role: "user", content: userContent }
|
|
1454
|
-
],
|
|
1455
|
-
temperature: 0.2
|
|
1456
|
-
}),
|
|
1479
|
+
body: JSON.stringify(requestBody),
|
|
1457
1480
|
signal: controller.signal
|
|
1458
1481
|
});
|
|
1482
|
+
debugLog(debug, "llm", `response status: ${res.status} ${res.statusText}`);
|
|
1459
1483
|
if (!res.ok) {
|
|
1460
1484
|
const errBody = await res.text().catch(() => "");
|
|
1485
|
+
debugLogBlock(debug, "llm", "error response body", errBody);
|
|
1461
1486
|
throw new Error(
|
|
1462
1487
|
`LLM API \u9519\u8BEF (${res.status}): ${errBody.slice(0, 300)}`
|
|
1463
1488
|
);
|
|
1464
1489
|
}
|
|
1465
1490
|
const data = await res.json();
|
|
1491
|
+
debugLogBlock(debug, "llm", "response json", JSON.stringify(data, null, 2));
|
|
1466
1492
|
const rawContent = data.choices?.[0]?.message?.content;
|
|
1467
1493
|
if (!rawContent) {
|
|
1468
1494
|
throw new Error("LLM \u8FD4\u56DE\u5185\u5BB9\u4E3A\u7A7A");
|
|
1469
1495
|
}
|
|
1496
|
+
debugLogBlock(debug, "llm", "raw message content", rawContent);
|
|
1470
1497
|
let parsed;
|
|
1471
1498
|
try {
|
|
1472
1499
|
parsed = JSON.parse(rawContent);
|
|
1473
1500
|
} catch {
|
|
1474
1501
|
throw new Error("LLM \u8FD4\u56DE\u5185\u5BB9\u4E0D\u662F\u5408\u6CD5 JSON");
|
|
1475
1502
|
}
|
|
1476
|
-
|
|
1503
|
+
debugLogBlock(debug, "llm", "parsed content", JSON.stringify(parsed, null, 2));
|
|
1504
|
+
const normalized = validateAndNormalizeLlmResult(parsed);
|
|
1505
|
+
debugLog(
|
|
1506
|
+
debug,
|
|
1507
|
+
"llm",
|
|
1508
|
+
`normalized: knowledgeFiles=${normalized.knowledgeFiles.length}, memoryChars=${normalized.memoryMd.length}, skippedSessions=${normalized.skippedSessions.length}`
|
|
1509
|
+
);
|
|
1510
|
+
debugLogBlock(
|
|
1511
|
+
debug,
|
|
1512
|
+
"llm",
|
|
1513
|
+
"normalized knowledgeFiles",
|
|
1514
|
+
JSON.stringify(normalized.knowledgeFiles, null, 2)
|
|
1515
|
+
);
|
|
1516
|
+
debugLogBlock(debug, "llm", "normalized memoryMd", normalized.memoryMd);
|
|
1517
|
+
debugLogBlock(
|
|
1518
|
+
debug,
|
|
1519
|
+
"llm",
|
|
1520
|
+
"normalized skippedSessions",
|
|
1521
|
+
JSON.stringify(normalized.skippedSessions, null, 2)
|
|
1522
|
+
);
|
|
1523
|
+
return normalized;
|
|
1524
|
+
} catch (err) {
|
|
1525
|
+
debugLog(
|
|
1526
|
+
debug,
|
|
1527
|
+
"llm",
|
|
1528
|
+
`error: ${err instanceof Error ? err.message : String(err)}`
|
|
1529
|
+
);
|
|
1530
|
+
throw err;
|
|
1477
1531
|
} finally {
|
|
1478
1532
|
clearTimeout(timeout);
|
|
1479
1533
|
}
|
|
@@ -1518,16 +1572,51 @@ function validateAndNormalizeLlmResult(raw) {
|
|
|
1518
1572
|
function normalizeKnowledgeFile(raw) {
|
|
1519
1573
|
if (!raw || typeof raw !== "object") return null;
|
|
1520
1574
|
const obj = raw;
|
|
1521
|
-
|
|
1575
|
+
const targetPath = typeof obj.targetPath === "string" ? obj.targetPath : typeof obj.path === "string" ? obj.path : null;
|
|
1576
|
+
if (!targetPath || !["create", "update"].includes(obj.action) || typeof obj.body !== "string") {
|
|
1522
1577
|
return null;
|
|
1523
1578
|
}
|
|
1524
1579
|
return {
|
|
1525
|
-
targetPath
|
|
1580
|
+
targetPath,
|
|
1526
1581
|
action: obj.action,
|
|
1527
|
-
frontmatter:
|
|
1582
|
+
frontmatter: normalizeFrontmatter(obj.frontmatter),
|
|
1528
1583
|
body: obj.body
|
|
1529
1584
|
};
|
|
1530
1585
|
}
|
|
1586
|
+
function normalizeFrontmatter(raw) {
|
|
1587
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
1588
|
+
return raw;
|
|
1589
|
+
}
|
|
1590
|
+
if (typeof raw !== "string") {
|
|
1591
|
+
return {};
|
|
1592
|
+
}
|
|
1593
|
+
const text = raw.trim();
|
|
1594
|
+
const yaml = text.startsWith("---") ? text.replace(/^---\r?\n?/, "").replace(/\r?\n?---$/, "") : text;
|
|
1595
|
+
const frontmatter = {};
|
|
1596
|
+
for (const line of yaml.split(/\r?\n/)) {
|
|
1597
|
+
const trimmed = line.trim();
|
|
1598
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
const separator = trimmed.indexOf(":");
|
|
1602
|
+
if (separator <= 0) {
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
const key = trimmed.slice(0, separator).trim();
|
|
1606
|
+
const value = trimmed.slice(separator + 1).trim();
|
|
1607
|
+
frontmatter[key] = parseFrontmatterValue(value);
|
|
1608
|
+
}
|
|
1609
|
+
return frontmatter;
|
|
1610
|
+
}
|
|
1611
|
+
function parseFrontmatterValue(value) {
|
|
1612
|
+
const unquoted = value.replace(/^["']|["']$/g, "");
|
|
1613
|
+
if (unquoted.startsWith("[") && unquoted.endsWith("]")) {
|
|
1614
|
+
return unquoted.slice(1, -1).split(",").map((item) => item.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
1615
|
+
}
|
|
1616
|
+
if (unquoted === "true") return true;
|
|
1617
|
+
if (unquoted === "false") return false;
|
|
1618
|
+
return unquoted;
|
|
1619
|
+
}
|
|
1531
1620
|
function isSkippedEntry(raw) {
|
|
1532
1621
|
if (!raw || typeof raw !== "object") return false;
|
|
1533
1622
|
const obj = raw;
|
|
@@ -1769,7 +1858,7 @@ async function runConsolidate(opts) {
|
|
|
1769
1858
|
);
|
|
1770
1859
|
let llmResult;
|
|
1771
1860
|
try {
|
|
1772
|
-
llmResult = await callLlmConsolidate(llmInput, llmConfig);
|
|
1861
|
+
llmResult = await callLlmConsolidate(llmInput, llmConfig, debug === true);
|
|
1773
1862
|
} catch (err) {
|
|
1774
1863
|
console.error(`[consolidate] LLM \u8C03\u7528\u5931\u8D25: ${err.message}`);
|
|
1775
1864
|
throw err;
|