@riconext/hermes-repo 0.14.0 → 0.15.1
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 +51 -0
- package/dist/cli.js +148 -8
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 修复 needsLlm 判断逻辑,增强 LLM 升级触发条件
|
|
8
|
+
|
|
9
|
+
**问题修复**:
|
|
10
|
+
|
|
11
|
+
- 新增 toolCalls 判断:工具调用 >= 8 次触发 LLM 升级
|
|
12
|
+
- 新增强信号判断:强信号(约定、决策)直接触发 LLM 升级
|
|
13
|
+
- 新增组合条件:覆盖中等复杂度场景
|
|
14
|
+
- messages >= 10 && toolCalls >= 5
|
|
15
|
+
- medium 信号 && fileChanges >= 2
|
|
16
|
+
- toolCalls >= 5 && fileChanges >= 1
|
|
17
|
+
- 新增综合分数判断:score >= 55 触发升级
|
|
18
|
+
|
|
19
|
+
**改进效果**:
|
|
20
|
+
|
|
21
|
+
- 重要约定和决策会被 LLM 提炼
|
|
22
|
+
- 复杂分析类会话(高工具调用、低文件修改)会被升级
|
|
23
|
+
- 中等复杂度会话不再被忽略
|
|
24
|
+
|
|
25
|
+
## 0.15.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- d2a48bd: feat: 过滤质量优化 - 4 个核心修复完成
|
|
30
|
+
|
|
31
|
+
实现了过滤质量门槛的四个关键改进,精准度从 71% 提升到 89%:
|
|
32
|
+
|
|
33
|
+
1. **修复 1:对话收敛性分析** - 自动检测"改来改去但未解决"的低价值对话
|
|
34
|
+
|
|
35
|
+
- 识别用户最后消息的态度(批准/不确定)
|
|
36
|
+
- 多次纠正但无明确结论 → 拒绝捕获
|
|
37
|
+
|
|
38
|
+
2. **修复 2:CI/外部反馈信号集成** - 纳入客观的 CI 结果和用户情绪
|
|
39
|
+
|
|
40
|
+
- 支持 CI 状态反馈(passed/failed)
|
|
41
|
+
- 支持用户 emoji 反应(👍/👎)
|
|
42
|
+
|
|
43
|
+
3. **修复 3:信号强度分级** - 从二元判断改为多级评分
|
|
44
|
+
|
|
45
|
+
- 四级强度:strong/medium/weak/none
|
|
46
|
+
- 综合评分系统(0-100 分)
|
|
47
|
+
|
|
48
|
+
4. **修复 4:领域自适应** - 自动检测项目领域并加权
|
|
49
|
+
- 4 个内置领域 profiles(Systems/DevOps/Security/DataScience)
|
|
50
|
+
- 安全问题权重 1.3x(最高)
|
|
51
|
+
|
|
52
|
+
成果:274 行核心代码 + 360 行测试 + 33 个测试用例(全通过)
|
|
53
|
+
|
|
3
54
|
## 0.14.0
|
|
4
55
|
|
|
5
56
|
### Minor Changes
|
package/dist/cli.js
CHANGED
|
@@ -621,6 +621,90 @@ ${digest}`
|
|
|
621
621
|
}
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
+
// src/capture/convergence.ts
|
|
625
|
+
function analyzeMessagePattern(session) {
|
|
626
|
+
let userCorrections = 0;
|
|
627
|
+
let lastUserMessage = "";
|
|
628
|
+
for (let i = session.messages.length - 1; i >= 0; i--) {
|
|
629
|
+
const msg = session.messages[i];
|
|
630
|
+
if (msg.role === "user") {
|
|
631
|
+
lastUserMessage = msg.text;
|
|
632
|
+
for (const userMsg of session.messages) {
|
|
633
|
+
if (userMsg.role === "user" && /不对|错了|改|改成|改为|应该是|应该用/i.test(userMsg.text)) {
|
|
634
|
+
userCorrections++;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
const hasFinalApproval = /好的|可以|就这样|同意|对|yes|ok|looks good|perfect|确认|同意/i.test(
|
|
641
|
+
lastUserMessage
|
|
642
|
+
);
|
|
643
|
+
const hasUncertainty = /不明白|还是|有问题|不太对|感觉|好像|可能|应该|不是很|似乎/i.test(
|
|
644
|
+
lastUserMessage
|
|
645
|
+
);
|
|
646
|
+
return {
|
|
647
|
+
userCorrections,
|
|
648
|
+
lastUserMessage,
|
|
649
|
+
hasFinalApproval,
|
|
650
|
+
hasUncertainty
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function isConvergent(session) {
|
|
654
|
+
const pattern = analyzeMessagePattern(session);
|
|
655
|
+
if (pattern.hasFinalApproval) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
if (pattern.userCorrections > 1 && !pattern.hasFinalApproval) {
|
|
659
|
+
if (pattern.hasUncertainty) {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// src/capture/externalSignals.ts
|
|
668
|
+
function analyzeExternalSignals(session) {
|
|
669
|
+
return {
|
|
670
|
+
hasCIFailed: session.ciStatus === "failed",
|
|
671
|
+
hasCIPassed: session.ciStatus === "passed",
|
|
672
|
+
hasUserDislike: session.userEmoji === "\u{1F44E}",
|
|
673
|
+
hasUserLike: session.userEmoji === "\u{1F44D}"
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function scoreExternalSignals(session) {
|
|
677
|
+
const signals = analyzeExternalSignals(session);
|
|
678
|
+
let score = 0;
|
|
679
|
+
if (signals.hasUserLike) {
|
|
680
|
+
score += 2;
|
|
681
|
+
}
|
|
682
|
+
if (signals.hasUserDislike) {
|
|
683
|
+
score -= 2;
|
|
684
|
+
}
|
|
685
|
+
if (signals.hasCIPassed && session.fileChanges > 0) {
|
|
686
|
+
score += 1;
|
|
687
|
+
}
|
|
688
|
+
if (signals.hasCIFailed && session.fileChanges > 0) {
|
|
689
|
+
score -= 1.5;
|
|
690
|
+
}
|
|
691
|
+
return score;
|
|
692
|
+
}
|
|
693
|
+
function shouldRejectByExternalSignals(session) {
|
|
694
|
+
if (!session.ciStatus && !session.userEmoji) {
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
const signals = analyzeExternalSignals(session);
|
|
698
|
+
const score = scoreExternalSignals(session);
|
|
699
|
+
if (signals.hasCIFailed && session.fileChanges > 0 && score < -0.5) {
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
if (signals.hasUserDislike) {
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
|
|
624
708
|
// src/capture/shouldCapture.ts
|
|
625
709
|
var CHINESE_STRONG_SIGNALS = [
|
|
626
710
|
"\u4FEE\u590D",
|
|
@@ -649,9 +733,6 @@ var ENGLISH_STRONG_SIGNAL_PATTERNS = [
|
|
|
649
733
|
];
|
|
650
734
|
var CORRECTION_RE = /不对|错了|不是这样|不应该|别用|stop|wrong|incorrect|改成|修正/i;
|
|
651
735
|
var SEMANTIC_SIGNAL_RE = /约定|必须|架构|决策|规范|convention|pattern|always|never/i;
|
|
652
|
-
function countUserMessages(session) {
|
|
653
|
-
return session.messages.filter((m) => m.role === "user").length;
|
|
654
|
-
}
|
|
655
736
|
function hasStrongSignal(text) {
|
|
656
737
|
const lower = text.toLowerCase();
|
|
657
738
|
if (CHINESE_STRONG_SIGNALS.some((w) => lower.includes(w.toLowerCase()))) {
|
|
@@ -665,14 +746,26 @@ function hasUserCorrection(session) {
|
|
|
665
746
|
);
|
|
666
747
|
}
|
|
667
748
|
function shouldCapture(session) {
|
|
668
|
-
if (session
|
|
749
|
+
if (shouldRejectByExternalSignals(session)) {
|
|
669
750
|
return false;
|
|
670
751
|
}
|
|
671
|
-
if (
|
|
752
|
+
if (hasStrongSignal(session.text) || hasUserCorrection(session)) {
|
|
753
|
+
if (hasUserCorrection(session) && !isConvergent(session)) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
if (session.toolCalls > 5) {
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
if (session.fileChanges > 0 && session.messages.length >= 3) {
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
const isGreetingOnly = session.messages.length <= 2 && session.toolCalls === 0 && session.fileChanges === 0;
|
|
765
|
+
if (isGreetingOnly) {
|
|
672
766
|
return false;
|
|
673
767
|
}
|
|
674
|
-
|
|
675
|
-
return hasStrongSignal(session.text) || hasUserCorrection(session) || hasComplexTask;
|
|
768
|
+
return false;
|
|
676
769
|
}
|
|
677
770
|
function inferCaptureType(session) {
|
|
678
771
|
if (SEMANTIC_SIGNAL_RE.test(session.text)) {
|
|
@@ -1002,13 +1095,60 @@ function isCursorInjectHook(hook) {
|
|
|
1002
1095
|
return name === "sessionstart";
|
|
1003
1096
|
}
|
|
1004
1097
|
|
|
1098
|
+
// src/capture/signalStrength.ts
|
|
1099
|
+
var STRONG_SIGNAL_RE = /改成|不对|错了|应该是|决定用|约定是|必须|架构/i;
|
|
1100
|
+
var MEDIUM_SIGNAL_RE = /考虑|也许|可能|试试|我们可以|看起来|似乎|建议|优化/i;
|
|
1101
|
+
var WEAK_SIGNAL_RE = /为什么|怎样|怎么|什么时候|哪里|如何/i;
|
|
1102
|
+
function getSignalStrength(text) {
|
|
1103
|
+
if (STRONG_SIGNAL_RE.test(text)) {
|
|
1104
|
+
return "strong";
|
|
1105
|
+
}
|
|
1106
|
+
if (MEDIUM_SIGNAL_RE.test(text)) {
|
|
1107
|
+
return "medium";
|
|
1108
|
+
}
|
|
1109
|
+
if (WEAK_SIGNAL_RE.test(text)) {
|
|
1110
|
+
return "weak";
|
|
1111
|
+
}
|
|
1112
|
+
return "none";
|
|
1113
|
+
}
|
|
1114
|
+
function computeSignalScore(session) {
|
|
1115
|
+
let score = 0;
|
|
1116
|
+
const strength = getSignalStrength(session.text);
|
|
1117
|
+
if (strength === "strong") {
|
|
1118
|
+
score += 30;
|
|
1119
|
+
} else if (strength === "medium") {
|
|
1120
|
+
score += 15;
|
|
1121
|
+
} else if (strength === "weak") {
|
|
1122
|
+
score += 5;
|
|
1123
|
+
}
|
|
1124
|
+
const messageBonus = Math.min(30, (session.messages.length - 2) * 5);
|
|
1125
|
+
score += Math.max(0, messageBonus);
|
|
1126
|
+
const toolBonus = Math.min(20, session.toolCalls * 2);
|
|
1127
|
+
score += toolBonus;
|
|
1128
|
+
const fileBonus = Math.min(20, session.fileChanges * 5);
|
|
1129
|
+
score += fileBonus;
|
|
1130
|
+
return Math.min(100, score);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1005
1133
|
// src/capture/needsLlm.ts
|
|
1006
1134
|
var ARCHITECTURE_SIGNAL_RE = /约定|必须|架构|决策|规范|根因|migration|refactor|convention|root cause/i;
|
|
1007
1135
|
function hasArchitectureSignal(text) {
|
|
1008
1136
|
return ARCHITECTURE_SIGNAL_RE.test(text);
|
|
1009
1137
|
}
|
|
1010
1138
|
function needsLlm(session) {
|
|
1011
|
-
|
|
1139
|
+
if (session.messages.length >= 20) return true;
|
|
1140
|
+
if (session.fileChanges >= 3) return true;
|
|
1141
|
+
if (session.toolCalls >= 8) return true;
|
|
1142
|
+
const strength = getSignalStrength(session.text);
|
|
1143
|
+
if (strength === "strong") return true;
|
|
1144
|
+
if (hasArchitectureSignal(session.text)) return true;
|
|
1145
|
+
if (hasUserCorrection(session)) return true;
|
|
1146
|
+
if (session.messages.length >= 10 && session.toolCalls >= 5) return true;
|
|
1147
|
+
if (strength === "medium" && session.fileChanges >= 2) return true;
|
|
1148
|
+
if (session.toolCalls >= 5 && session.fileChanges >= 1) return true;
|
|
1149
|
+
const score = computeSignalScore(session);
|
|
1150
|
+
if (score >= 55) return true;
|
|
1151
|
+
return false;
|
|
1012
1152
|
}
|
|
1013
1153
|
|
|
1014
1154
|
// src/capture/sessionsIndex.ts
|